From 1bdae99180f37d805170f72867639b57db8b732d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cau=C3=AA=20Marcondes?=
<55978943+cauemarcondes@users.noreply.github.com>
Date: Mon, 11 Apr 2022 11:19:43 -0400
Subject: [PATCH 01/75] [APM] fix error count e2e flaky test (#129755)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../power_user/rules/error_count.spec.ts | 6 ++--
x-pack/plugins/apm/scripts/test/e2e.js | 33 +++++++++++++++++--
2 files changed, 34 insertions(+), 5 deletions(-)
diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/rules/error_count.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/rules/error_count.spec.ts
index e53b84ca76496..27830a4f74892 100644
--- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/rules/error_count.spec.ts
+++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/rules/error_count.spec.ts
@@ -51,12 +51,14 @@ describe('Rules', () => {
cy.contains('Alerts and rules').click();
cy.contains('Create error count rule').click();
- // Check for the existence of this element to make sure the form
+ // Check for the existence of these elements to make sure the form
// has loaded.
cy.contains('for the last');
+ cy.contains('Actions');
+ cy.contains('Save').should('not.be.disabled');
// Save, with no actions
- cy.contains('button:not(:disabled)', 'Save').click();
+ cy.contains('Save').click();
cy.get(confirmModalButtonSelector).click();
cy.contains(`Created rule "${ruleName}`);
diff --git a/x-pack/plugins/apm/scripts/test/e2e.js b/x-pack/plugins/apm/scripts/test/e2e.js
index 148d5011b1ecb..a4a0cc79cac2d 100644
--- a/x-pack/plugins/apm/scripts/test/e2e.js
+++ b/x-pack/plugins/apm/scripts/test/e2e.js
@@ -6,7 +6,7 @@
*/
/* eslint-disable no-console */
-
+const { times } = require('lodash');
const path = require('path');
const yargs = require('yargs');
const childProcess = require('child_process');
@@ -45,6 +45,10 @@ const { argv } = yargs(process.argv.slice(2))
type: 'boolean',
description: 'stop tests after the first failure',
})
+ .option('times', {
+ type: 'number',
+ description: 'Repeat the test n number of times',
+ })
.help();
const { server, runner, open, grep, bail, kibanaInstallDir } = argv;
@@ -63,5 +67,28 @@ const grepArg = grep ? `--grep "${grep}"` : '';
const bailArg = bail ? `--bail` : '';
const cmd = `node ../../../../scripts/${ftrScript} --config ${config} ${grepArg} ${bailArg} --kibana-install-dir '${kibanaInstallDir}'`;
-console.log(`Running "${cmd}"`);
-childProcess.execSync(cmd, { cwd: e2eDir, stdio: 'inherit' });
+function runTests() {
+ console.log(`Running "${cmd}"`);
+ childProcess.execSync(cmd, { cwd: e2eDir, stdio: 'inherit' });
+}
+
+if (argv.times) {
+ const runCounter = { succeeded: 0, failed: 0, remaining: argv.times };
+ let exitStatus = 0;
+ times(argv.times, () => {
+ try {
+ runTests();
+ runCounter.succeeded++;
+ } catch (e) {
+ exitStatus = 1;
+ runCounter.failed++;
+ }
+ runCounter.remaining--;
+ if (argv.times > 1) {
+ console.log(runCounter);
+ }
+ });
+ process.exit(exitStatus);
+} else {
+ runTests();
+}
From d7114900f522cba9580b5385a7f2f32a844f0758 Mon Sep 17 00:00:00 2001
From: Tre
Date: Mon, 11 Apr 2022 16:31:46 +0100
Subject: [PATCH 02/75] [QA][Code Coverage] Ingest the correct id for the ci
job (#129622)
Resolves: https://github.com/elastic/kibana/issues/129617
Use the build number instead of the uuid.
---
.buildkite/scripts/steps/code_coverage/ingest.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.buildkite/scripts/steps/code_coverage/ingest.sh b/.buildkite/scripts/steps/code_coverage/ingest.sh
index a9b95cccb533c..f806b6fa149c2 100755
--- a/.buildkite/scripts/steps/code_coverage/ingest.sh
+++ b/.buildkite/scripts/steps/code_coverage/ingest.sh
@@ -52,4 +52,4 @@ echo "--- Upload coverage static site"
.buildkite/scripts/steps/code_coverage/reporting/uploadStaticSite.sh
echo "--- Ingest results to Kibana stats cluster"
-.buildkite/scripts/steps/code_coverage/reporting/ingestData.sh 'elastic+kibana+code-coverage' ${BUILDKITE_BUILD_ID} ${BUILDKITE_BUILD_URL} ${previousSha} 'src/dev/code_coverage/ingest_coverage/team_assignment/team_assignments.txt'
+.buildkite/scripts/steps/code_coverage/reporting/ingestData.sh 'elastic+kibana+code-coverage' ${BUILDKITE_BUILD_NUMBER} ${BUILDKITE_BUILD_URL} ${previousSha} 'src/dev/code_coverage/ingest_coverage/team_assignment/team_assignments.txt'
From 980a97f145668676e3937f75c02ba8226817ee6b Mon Sep 17 00:00:00 2001
From: Pablo Machado
Date: Mon, 11 Apr 2022 17:43:04 +0200
Subject: [PATCH 03/75] Add the authentication tab to the user details page
(#129456)
* Add the authentication tab to the user details page
* Update i18n
* Please code review
* Add MatrixHistogram to authentications tab
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../integration/users/users_tabs.spec.ts | 65 +++--
.../security_solution/cypress/tasks/login.ts | 2 +-
.../authentications_host_table.tsx | 2 +-
.../authentications_user_table.test.tsx | 25 ++
.../authentications_user_table.tsx | 24 +-
.../components/authentication/helpers.tsx | 78 +++++-
.../components/authentication/translations.ts | 28 ++-
.../common/components/authentication/types.ts | 26 +-
.../{hosts => common}/authentication.ts | 0
.../authentications_query_tab_body.tsx | 49 +---
.../public/users/pages/constants.ts | 2 +-
.../users/pages/details/details_tabs.tsx | 4 +
.../public/users/pages/details/nav_tabs.tsx | 6 +
.../public/users/pages/index.tsx | 9 +-
.../authentications_query_tab_body.tsx | 45 ++--
.../translations/translations/fr-FR.json | 233 +++++++++---------
.../translations/translations/ja-JP.json | 1 -
.../translations/translations/zh-CN.json | 1 -
.../es_archives/users/data.json | 6 +
19 files changed, 354 insertions(+), 252 deletions(-)
rename x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/{hosts => common}/authentication.ts (100%)
diff --git a/x-pack/plugins/security_solution/cypress/integration/users/users_tabs.spec.ts b/x-pack/plugins/security_solution/cypress/integration/users/users_tabs.spec.ts
index 8981e2be121b9..6ae79f41ffc60 100644
--- a/x-pack/plugins/security_solution/cypress/integration/users/users_tabs.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/users/users_tabs.spec.ts
@@ -20,7 +20,7 @@ import { RISK_SCORE_TAB, RISK_SCORE_TAB_CONTENT } from '../../screens/users/user
import { cleanKibana } from '../../tasks/common';
import { esArchiverLoad, esArchiverUnload } from '../../tasks/es_archiver';
-import { login, visit } from '../../tasks/login';
+import { login, visit, visitUserDetailsPage } from '../../tasks/login';
import { USERS_URL } from '../../urls/navigation';
@@ -35,43 +35,56 @@ describe('Users stats and tables', () => {
esArchiverUnload('users');
});
- it(`renders all users`, () => {
- const totalUsers = 1;
+ describe('Users page tabs', () => {
+ it(`renders all users`, () => {
+ const totalUsers = 1;
- cy.get(HEADER_SUBTITLE).should('have.text', `Showing: ${totalUsers} user`);
- });
+ cy.get(HEADER_SUBTITLE).should('have.text', `Showing: ${totalUsers} user`);
+ });
- it(`renders all authentications`, () => {
- const totalUsers = 1;
+ it(`renders all authentications`, () => {
+ const totalUsers = 1;
- cy.get(AUTHENTICATIONS_TAB).click();
+ cy.get(AUTHENTICATIONS_TAB).click();
- cy.get(AUTHENTICATIONS_TABLE)
- .find(HEADER_SUBTITLE)
- .should('have.text', `Showing: ${totalUsers} user`);
- });
+ cy.get(AUTHENTICATIONS_TABLE)
+ .find(HEADER_SUBTITLE)
+ .should('have.text', `Showing: ${totalUsers} user`);
+ });
- it(`renders anomalies tab`, () => {
- cy.get(ANOMALIES_TAB).click({ force: true });
+ it(`renders anomalies tab`, () => {
+ cy.get(ANOMALIES_TAB).click({ force: true });
- cy.get(ANOMALIES_TAB_CONTENT).should('exist');
- });
+ cy.get(ANOMALIES_TAB_CONTENT).should('exist');
+ });
- it(`renders events tab`, () => {
- cy.get(EVENTS_TAB).click({ force: true });
+ it(`renders events tab`, () => {
+ cy.get(EVENTS_TAB).click({ force: true });
- cy.get(EVENTS_TAB_CONTENT).should('exist');
- });
+ cy.get(EVENTS_TAB_CONTENT).should('exist');
+ });
+
+ it(`renders external alerts tab`, () => {
+ cy.get(EXTERNAL_ALERTS_TAB).click({ force: true });
+
+ cy.get(EXTERNAL_ALERTS_TAB_CONTENT).should('exist');
+ });
- it(`renders external alerts tab`, () => {
- cy.get(EXTERNAL_ALERTS_TAB).click({ force: true });
+ it(`renders users risk tab`, () => {
+ cy.get(RISK_SCORE_TAB).click({ force: true });
- cy.get(EXTERNAL_ALERTS_TAB_CONTENT).should('exist');
+ cy.get(RISK_SCORE_TAB_CONTENT).should('exist');
+ });
});
- it(`renders users risk tab`, () => {
- cy.get(RISK_SCORE_TAB).click({ force: true });
+ describe('User details tabs', () => {
+ it(`renders authentications tab`, () => {
+ visitUserDetailsPage();
+ const totalUsers = 1;
- cy.get(RISK_SCORE_TAB_CONTENT).should('exist');
+ cy.get(AUTHENTICATIONS_TABLE)
+ .find(HEADER_SUBTITLE)
+ .should('have.text', `Showing: ${totalUsers} host`);
+ });
});
});
diff --git a/x-pack/plugins/security_solution/cypress/tasks/login.ts b/x-pack/plugins/security_solution/cypress/tasks/login.ts
index 27f60ff16f5da..f2beaa28ab8b6 100644
--- a/x-pack/plugins/security_solution/cypress/tasks/login.ts
+++ b/x-pack/plugins/security_solution/cypress/tasks/login.ts
@@ -352,7 +352,7 @@ export const visitHostDetailsPage = (hostName = 'suricata-iowa') => {
cy.get('[data-test-subj="loading-spinner"]').should('not.exist');
};
-export const visitUserDetailsPage = (userName = 'bob') => {
+export const visitUserDetailsPage = (userName = 'test') => {
visit(userDetailsUrl(userName));
};
diff --git a/x-pack/plugins/security_solution/public/common/components/authentication/authentications_host_table.tsx b/x-pack/plugins/security_solution/public/common/components/authentication/authentications_host_table.tsx
index 710b862570086..a62947e19ba7e 100644
--- a/x-pack/plugins/security_solution/public/common/components/authentication/authentications_host_table.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/authentication/authentications_host_table.tsx
@@ -115,7 +115,7 @@ const AuthenticationsHostTableComponent: React.FC = (
dataTestSubj="authentications-host-table"
headerCount={totalCount}
headerTitle={i18n.AUTHENTICATIONS}
- headerUnit={i18n.UNIT(totalCount)}
+ headerUnit={i18n.USERS_UNIT(totalCount)}
id={TABLE_QUERY_ID}
isInspect={isInspected}
itemsPerRow={rowItems}
diff --git a/x-pack/plugins/security_solution/public/common/components/authentication/authentications_user_table.test.tsx b/x-pack/plugins/security_solution/public/common/components/authentication/authentications_user_table.test.tsx
index 6be9c630a20bf..45aa387ca1bcc 100644
--- a/x-pack/plugins/security_solution/public/common/components/authentication/authentications_user_table.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/authentication/authentications_user_table.test.tsx
@@ -14,6 +14,7 @@ import { useAuthentications } from '../../../common/containers/authentications';
import { useQueryToggle } from '../../../common/containers/query_toggle';
import { AuthenticationsUserTable } from './authentications_user_table';
import { usersModel } from '../../../users/store';
+import { AuthStackByField } from '../../../../common/search_strategy';
jest.mock('../../../common/containers/query_toggle', () => ({
useQueryToggle: jest.fn().mockReturnValue({ toggleStatus: true, setToggleStatus: jest.fn() }),
@@ -82,4 +83,28 @@ describe('Authentication User Table Component', () => {
);
expect(mockUseAuthentications.mock.calls[0][0].skip).toEqual(true);
});
+
+ describe('useAuthentications', () => {
+ it('calls useAuthentications stacked by username when username is undefined', () => {
+ render(
+
+
+
+ );
+ expect(mockUseAuthentications.mock.calls[0][0].stackByField).toEqual(
+ AuthStackByField.userName
+ );
+ });
+
+ it('calls useAuthentications stacked by hostname when there username is defined', () => {
+ render(
+
+
+
+ );
+ expect(mockUseAuthentications.mock.calls[0][0].stackByField).toEqual(
+ AuthStackByField.hostName
+ );
+ });
+ });
});
diff --git a/x-pack/plugins/security_solution/public/common/components/authentication/authentications_user_table.tsx b/x-pack/plugins/security_solution/public/common/components/authentication/authentications_user_table.tsx
index 572c06ef4da90..312670038e96e 100644
--- a/x-pack/plugins/security_solution/public/common/components/authentication/authentications_user_table.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/authentication/authentications_user_table.tsx
@@ -12,20 +12,22 @@ import { useDispatch } from 'react-redux';
import { AuthStackByField } from '../../../../common/search_strategy/security_solution/users/authentications';
import { PaginatedTable } from '../paginated_table';
-import { useIsExperimentalFeatureEnabled } from '../../hooks/use_experimental_features';
-
import * as i18n from './translations';
-import { getHostsPageAuthenticationColumns, rowItems } from './helpers';
+import {
+ getUserDetailsAuthenticationColumns,
+ getUsersPageAuthenticationColumns,
+ rowItems,
+} from './helpers';
import { useAuthentications } from '../../containers/authentications';
import { useQueryInspector } from '../page/manage_query';
import { useQueryToggle } from '../../containers/query_toggle';
import { useDeepEqualSelector } from '../../hooks/use_selector';
import { usersActions, usersModel, usersSelectors } from '../../../users/store';
-import { UsersComponentsQueryProps } from '../../../users/pages/navigation/types';
+import { AuthenticationsUserTableProps } from './types';
const TABLE_QUERY_ID = 'authenticationsUsersTableQuery';
-const AuthenticationsUserTableComponent: React.FC = ({
+const AuthenticationsUserTableComponent: React.FC = ({
docValueFields,
endDate,
filterQuery,
@@ -35,9 +37,8 @@ const AuthenticationsUserTableComponent: React.FC = (
type,
setQuery,
deleteQuery,
+ userName,
}) => {
- const usersEnabled = useIsExperimentalFeatureEnabled('usersEnabled');
-
const dispatch = useDispatch();
const { toggleStatus } = useQueryToggle(TABLE_QUERY_ID);
const [querySkip, setQuerySkip] = useState(skip || !toggleStatus);
@@ -60,10 +61,13 @@ const AuthenticationsUserTableComponent: React.FC = (
startDate,
activePage,
limit,
- stackByField: AuthStackByField.userName,
+ stackByField: userName ? AuthStackByField.hostName : AuthStackByField.userName,
});
- const columns = getHostsPageAuthenticationColumns(usersEnabled);
+ const columns = useMemo(
+ () => (userName ? getUserDetailsAuthenticationColumns() : getUsersPageAuthenticationColumns()),
+ [userName]
+ );
const updateLimitPagination = useCallback(
(newLimit) =>
@@ -105,7 +109,7 @@ const AuthenticationsUserTableComponent: React.FC = (
dataTestSubj="table-users-authentications"
headerCount={totalCount}
headerTitle={i18n.AUTHENTICATIONS}
- headerUnit={i18n.UNIT(totalCount)}
+ headerUnit={userName ? i18n.HOSTS_UNIT(totalCount) : i18n.USERS_UNIT(totalCount)}
id={TABLE_QUERY_ID}
isInspect={isInspected}
itemsPerRow={rowItems}
diff --git a/x-pack/plugins/security_solution/public/common/components/authentication/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/authentication/helpers.tsx
index d541e0e452943..bff5072043527 100644
--- a/x-pack/plugins/security_solution/public/common/components/authentication/helpers.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/authentication/helpers.tsx
@@ -19,8 +19,15 @@ import { getRowItemDraggables } from '../tables/helpers';
import * as i18n from './translations';
import { HostDetailsLink, NetworkDetailsLink, UserDetailsLink } from '../links';
-import { AuthenticationsEdges } from '../../../../common/search_strategy';
+import { AuthenticationsEdges, MatrixHistogramType } from '../../../../common/search_strategy';
import { AuthTableColumns } from './types';
+import {
+ MatrixHistogramConfigs,
+ MatrixHistogramMappingTypes,
+ MatrixHistogramOption,
+} from '../matrix_histogram/types';
+import { LensAttributes } from '../visualization_actions/types';
+import { authenticationLensAttributes } from '../visualization_actions/lens_attributes/common/authentication';
export const getHostDetailsAuthenticationColumns = (usersEnabled: boolean): AuthTableColumns => [
getUserColumn(usersEnabled),
@@ -44,6 +51,19 @@ export const getHostsPageAuthenticationColumns = (usersEnabled: boolean): AuthTa
LAST_FAILED_DESTINATION_COLUMN,
];
+export const getUsersPageAuthenticationColumns = (): AuthTableColumns =>
+ getHostsPageAuthenticationColumns(true);
+
+export const getUserDetailsAuthenticationColumns = (): AuthTableColumns => [
+ HOST_COLUMN,
+ SUCCESS_COLUMN,
+ FAILURES_COLUMN,
+ LAST_SUCCESSFUL_TIME_COLUMN,
+ LAST_SUCCESSFUL_SOURCE_COLUMN,
+ LAST_FAILED_TIME_COLUMN,
+ LAST_FAILED_SOURCE_COLUMN,
+];
+
export const rowItems: ItemsPerRow[] = [
{
text: i18n.ROWS_5,
@@ -177,6 +197,19 @@ const getUserColumn = (
}),
});
+const HOST_COLUMN: Columns = {
+ name: i18n.HOST,
+ truncateText: false,
+ mobileOptions: { show: true },
+ render: ({ node }) =>
+ getRowItemDraggables({
+ rowItems: node.stackedValue,
+ attrName: 'host.name',
+ idPrefix: `authentications-table-${node._id}-hostName`,
+ render: (item) => ,
+ }),
+};
+
const SUCCESS_COLUMN: Columns = {
name: i18n.SUCCESSES,
truncateText: false,
@@ -215,3 +248,46 @@ const SUCCESS_COLUMN: Columns = {
},
width: '8%',
};
+
+export const authenticationsStackByOptions: MatrixHistogramOption[] = [
+ {
+ text: 'event.outcome',
+ value: 'event.outcome',
+ },
+];
+const DEFAULT_STACK_BY = 'event.outcome';
+
+enum AuthenticationsMatrixDataGroup {
+ authenticationsSuccess = 'success',
+ authenticationsFailure = 'failure',
+}
+
+export enum ChartColors {
+ authenticationsSuccess = '#54B399',
+ authenticationsFailure = '#E7664C',
+}
+
+export const authenticationsMatrixDataMappingFields: MatrixHistogramMappingTypes = {
+ [AuthenticationsMatrixDataGroup.authenticationsSuccess]: {
+ key: AuthenticationsMatrixDataGroup.authenticationsSuccess,
+ value: null,
+ color: ChartColors.authenticationsSuccess,
+ },
+ [AuthenticationsMatrixDataGroup.authenticationsFailure]: {
+ key: AuthenticationsMatrixDataGroup.authenticationsFailure,
+ value: null,
+ color: ChartColors.authenticationsFailure,
+ },
+};
+
+export const histogramConfigs: MatrixHistogramConfigs = {
+ defaultStackByOption:
+ authenticationsStackByOptions.find((o) => o.text === DEFAULT_STACK_BY) ??
+ authenticationsStackByOptions[0],
+ errorMessage: i18n.ERROR_FETCHING_AUTHENTICATIONS_DATA,
+ histogramType: MatrixHistogramType.authentications,
+ mapping: authenticationsMatrixDataMappingFields,
+ stackByOptions: authenticationsStackByOptions,
+ title: i18n.NAVIGATION_AUTHENTICATIONS_TITLE,
+ lensAttributes: authenticationLensAttributes as LensAttributes,
+};
diff --git a/x-pack/plugins/security_solution/public/common/components/authentication/translations.ts b/x-pack/plugins/security_solution/public/common/components/authentication/translations.ts
index 7dba26277eaa6..57566eec40c37 100644
--- a/x-pack/plugins/security_solution/public/common/components/authentication/translations.ts
+++ b/x-pack/plugins/security_solution/public/common/components/authentication/translations.ts
@@ -14,12 +14,18 @@ export const AUTHENTICATIONS = i18n.translate(
}
);
-export const UNIT = (totalCount: number) =>
- i18n.translate('xpack.securitySolution.authenticationsTable.unit', {
+export const USERS_UNIT = (totalCount: number) =>
+ i18n.translate('xpack.securitySolution.authenticationsTable.usersUnit', {
values: { totalCount },
defaultMessage: `{totalCount, plural, =1 {user} other {users}}`,
});
+export const HOSTS_UNIT = (totalCount: number) =>
+ i18n.translate('xpack.securitySolution.authenticationsTable.hostsUnit', {
+ values: { totalCount },
+ defaultMessage: `{totalCount, plural, =1 {host} other {hosts}}`,
+ });
+
export const LAST_SUCCESSFUL_SOURCE = i18n.translate(
'xpack.securitySolution.authenticationsTable.lastSuccessfulSource',
{
@@ -74,6 +80,10 @@ export const USER = i18n.translate('xpack.securitySolution.authenticationsTable.
defaultMessage: 'User',
});
+export const HOST = i18n.translate('xpack.securitySolution.authenticationsTable.host', {
+ defaultMessage: 'Host',
+});
+
export const ROWS_5 = i18n.translate('xpack.securitySolution.authenticationsTable.rows', {
values: { numRows: 5 },
defaultMessage: '{numRows} {numRows, plural, =0 {rows} =1 {row} other {rows}}',
@@ -83,3 +93,17 @@ export const ROWS_10 = i18n.translate('xpack.securitySolution.authenticationsTab
values: { numRows: 10 },
defaultMessage: '{numRows} {numRows, plural, =0 {rows} =1 {row} other {rows}}',
});
+
+export const NAVIGATION_AUTHENTICATIONS_TITLE = i18n.translate(
+ 'xpack.securitySolution.hosts.navigation.authenticationsTitle',
+ {
+ defaultMessage: 'Authentications',
+ }
+);
+
+export const ERROR_FETCHING_AUTHENTICATIONS_DATA = i18n.translate(
+ 'xpack.securitySolution.hosts.navigaton.matrixHistogram.errorFetchingAuthenticationsData',
+ {
+ defaultMessage: 'Failed to query authentications data',
+ }
+);
diff --git a/x-pack/plugins/security_solution/public/common/components/authentication/types.ts b/x-pack/plugins/security_solution/public/common/components/authentication/types.ts
index c686263fa8d12..4c1000dc8e1ac 100644
--- a/x-pack/plugins/security_solution/public/common/components/authentication/types.ts
+++ b/x-pack/plugins/security_solution/public/common/components/authentication/types.ts
@@ -6,26 +6,10 @@
*/
import { AuthenticationsEdges } from '../../../../common/search_strategy';
+import { UsersComponentsQueryProps } from '../../../users/pages/navigation/types';
import { Columns } from '../paginated_table';
-export type AuthTableColumns =
- | [
- Columns,
- Columns,
- Columns,
- Columns,
- Columns,
- Columns,
- Columns,
- Columns,
- Columns
- ]
- | [
- Columns,
- Columns,
- Columns,
- Columns,
- Columns,
- Columns,
- Columns
- ];
+export type AuthTableColumns = Array>;
+export interface AuthenticationsUserTableProps extends UsersComponentsQueryProps {
+ userName?: string;
+}
diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/authentication.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/authentication.ts
similarity index 100%
rename from x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/authentication.ts
rename to x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/authentication.ts
diff --git a/x-pack/plugins/security_solution/public/hosts/pages/navigation/authentications_query_tab_body.tsx b/x-pack/plugins/security_solution/public/hosts/pages/navigation/authentications_query_tab_body.tsx
index 0f6de80343b11..7f97c196ee172 100644
--- a/x-pack/plugins/security_solution/public/hosts/pages/navigation/authentications_query_tab_body.tsx
+++ b/x-pack/plugins/security_solution/public/hosts/pages/navigation/authentications_query_tab_body.tsx
@@ -7,59 +7,12 @@
import React from 'react';
import { HostsComponentsQueryProps } from './types';
-import {
- MatrixHistogramOption,
- MatrixHistogramMappingTypes,
- MatrixHistogramConfigs,
-} from '../../../common/components/matrix_histogram/types';
import { MatrixHistogram } from '../../../common/components/matrix_histogram';
-import { HostsKpiChartColors } from '../../components/kpi_hosts/types';
-import * as i18n from '../translations';
-import { MatrixHistogramType } from '../../../../common/search_strategy/security_solution';
-import { authenticationLensAttributes } from '../../../common/components/visualization_actions/lens_attributes/hosts/authentication';
-import { LensAttributes } from '../../../common/components/visualization_actions/types';
import { AuthenticationsHostTable } from '../../../common/components/authentication/authentications_host_table';
+import { histogramConfigs } from '../../../common/components/authentication/helpers';
const HISTOGRAM_QUERY_ID = 'authenticationsHistogramQuery';
-const authenticationsStackByOptions: MatrixHistogramOption[] = [
- {
- text: 'event.outcome',
- value: 'event.outcome',
- },
-];
-const DEFAULT_STACK_BY = 'event.outcome';
-
-enum AuthenticationsMatrixDataGroup {
- authenticationsSuccess = 'success',
- authenticationsFailure = 'failure',
-}
-
-export const authenticationsMatrixDataMappingFields: MatrixHistogramMappingTypes = {
- [AuthenticationsMatrixDataGroup.authenticationsSuccess]: {
- key: AuthenticationsMatrixDataGroup.authenticationsSuccess,
- value: null,
- color: HostsKpiChartColors.authenticationsSuccess,
- },
- [AuthenticationsMatrixDataGroup.authenticationsFailure]: {
- key: AuthenticationsMatrixDataGroup.authenticationsFailure,
- value: null,
- color: HostsKpiChartColors.authenticationsFailure,
- },
-};
-
-const histogramConfigs: MatrixHistogramConfigs = {
- defaultStackByOption:
- authenticationsStackByOptions.find((o) => o.text === DEFAULT_STACK_BY) ??
- authenticationsStackByOptions[0],
- errorMessage: i18n.ERROR_FETCHING_AUTHENTICATIONS_DATA,
- histogramType: MatrixHistogramType.authentications,
- mapping: authenticationsMatrixDataMappingFields,
- stackByOptions: authenticationsStackByOptions,
- title: i18n.NAVIGATION_AUTHENTICATIONS_TITLE,
- lensAttributes: authenticationLensAttributes as LensAttributes,
-};
-
const AuthenticationsQueryTabBodyComponent: React.FC = ({
deleteQuery,
docValueFields,
diff --git a/x-pack/plugins/security_solution/public/users/pages/constants.ts b/x-pack/plugins/security_solution/public/users/pages/constants.ts
index 39d8c1546c863..44d3b0ba83e1f 100644
--- a/x-pack/plugins/security_solution/public/users/pages/constants.ts
+++ b/x-pack/plugins/security_solution/public/users/pages/constants.ts
@@ -12,4 +12,4 @@ export const usersDetailsPagePath = `${USERS_PATH}/:detailName`;
export const usersTabPath = `${USERS_PATH}/:tabName(${UsersTableType.allUsers}|${UsersTableType.authentications}|${UsersTableType.anomalies}|${UsersTableType.risk}|${UsersTableType.events}|${UsersTableType.alerts})`;
-export const usersDetailsTabPath = `${usersDetailsPagePath}/:tabName(${UsersTableType.anomalies}|${UsersTableType.events}|${UsersTableType.alerts})`;
+export const usersDetailsTabPath = `${usersDetailsPagePath}/:tabName(${UsersTableType.authentications}|${UsersTableType.anomalies}|${UsersTableType.events}|${UsersTableType.alerts})`;
diff --git a/x-pack/plugins/security_solution/public/users/pages/details/details_tabs.tsx b/x-pack/plugins/security_solution/public/users/pages/details/details_tabs.tsx
index e23cac75b6cdf..d3c3a4607b39c 100644
--- a/x-pack/plugins/security_solution/public/users/pages/details/details_tabs.tsx
+++ b/x-pack/plugins/security_solution/public/users/pages/details/details_tabs.tsx
@@ -20,6 +20,7 @@ import { TimelineId } from '../../../../common/types';
import { EventsQueryTabBody } from '../../../common/components/events_tab/events_query_tab_body';
import { AlertsView } from '../../../common/components/alerts_viewer';
import { userNameExistsFilter } from './helpers';
+import { AuthenticationsQueryTabBody } from '../navigation';
export const UsersDetailsTabs = React.memo(
({
@@ -84,6 +85,9 @@ export const UsersDetailsTabs = React.memo(
return (
+
+
+
diff --git a/x-pack/plugins/security_solution/public/users/pages/details/nav_tabs.tsx b/x-pack/plugins/security_solution/public/users/pages/details/nav_tabs.tsx
index 9671bd4ee38d0..ee070f749925e 100644
--- a/x-pack/plugins/security_solution/public/users/pages/details/nav_tabs.tsx
+++ b/x-pack/plugins/security_solution/public/users/pages/details/nav_tabs.tsx
@@ -19,6 +19,12 @@ export const navTabsUsersDetails = (
hasMlUserPermissions: boolean
): UsersDetailsNavTab => {
const userDetailsNavTabs = {
+ [UsersTableType.authentications]: {
+ id: UsersTableType.authentications,
+ name: i18n.NAVIGATION_AUTHENTICATIONS_TITLE,
+ href: getTabsOnUsersDetailsUrl(userName, UsersTableType.authentications),
+ disabled: false,
+ },
[UsersTableType.anomalies]: {
id: UsersTableType.anomalies,
name: i18n.NAVIGATION_ANOMALIES_TITLE,
diff --git a/x-pack/plugins/security_solution/public/users/pages/index.tsx b/x-pack/plugins/security_solution/public/users/pages/index.tsx
index 0449ab59688fa..04b1122a39b54 100644
--- a/x-pack/plugins/security_solution/public/users/pages/index.tsx
+++ b/x-pack/plugins/security_solution/public/users/pages/index.tsx
@@ -12,13 +12,8 @@ import { UsersTableType } from '../store/model';
import { Users } from './users';
import { UsersDetails } from './details';
import { usersDetailsPagePath, usersDetailsTabPath, usersTabPath } from './constants';
-import { useMlCapabilities } from '../../common/components/ml/hooks/use_ml_capabilities';
-import { hasMlUserPermissions } from '../../../common/machine_learning/has_ml_user_permissions';
export const UsersContainer = React.memo(() => {
- const capabilities = useMlCapabilities();
- const hasMlPermissions = hasMlUserPermissions(capabilities);
-
return (
@@ -48,9 +43,7 @@ export const UsersContainer = React.memo(() => {
}) => (
diff --git a/x-pack/plugins/security_solution/public/users/pages/navigation/authentications_query_tab_body.tsx b/x-pack/plugins/security_solution/public/users/pages/navigation/authentications_query_tab_body.tsx
index 453ae6e9a8f3f..044a0e4de67ee 100644
--- a/x-pack/plugins/security_solution/public/users/pages/navigation/authentications_query_tab_body.tsx
+++ b/x-pack/plugins/security_solution/public/users/pages/navigation/authentications_query_tab_body.tsx
@@ -6,11 +6,14 @@
*/
import React from 'react';
-import { UsersComponentsQueryProps } from './types';
import { AuthenticationsUserTable } from '../../../common/components/authentication/authentications_user_table';
-
+import { histogramConfigs } from '../../../common/components/authentication/helpers';
+import { AuthenticationsUserTableProps } from '../../../common/components/authentication/types';
+import { MatrixHistogram } from '../../../common/components/matrix_histogram';
export const ID = 'usersAuthenticationsQuery';
+const HISTOGRAM_QUERY_ID = 'usersAuthenticationsHistogramQuery';
+
export const AuthenticationsQueryTabBody = ({
endDate,
filterQuery,
@@ -21,19 +24,33 @@ export const AuthenticationsQueryTabBody = ({
type,
docValueFields,
deleteQuery,
-}: UsersComponentsQueryProps) => {
+ userName,
+}: AuthenticationsUserTableProps) => {
return (
-
+ <>
+
+
+
+ >
);
};
diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json
index 8d800c8ba38aa..b6cc88c5a8c92 100644
--- a/x-pack/plugins/translations/translations/fr-FR.json
+++ b/x-pack/plugins/translations/translations/fr-FR.json
@@ -2108,13 +2108,127 @@
"data.search.timeoutContactAdmin": "Votre requête a expiré. Contactez l'administrateur système pour accroître le temps d'exécution.",
"data.search.timeoutIncreaseSetting": "Votre requête a expiré. Augmentez le temps d'exécution en utilisant le paramètre avancé de délai d'expiration de la recherche.",
"data.search.timeoutIncreaseSettingActionText": "Modifier le paramètre",
- "unifiedSearch.search.unableToGetSavedQueryToastTitle": "Impossible de charger la requête enregistrée {savedQueryId}",
"data.searchSession.warning.readDocs": "En savoir plus",
"data.searchSessionIndicator.noCapability": "Vous n'êtes pas autorisé à créer des sessions de recherche.",
"data.searchSessions.sessionService.sessionEditNameError": "Échec de modification du nom de la session de recherche",
"data.searchSessions.sessionService.sessionObjectFetchError": "Échec de récupération des informations de la session de recherche",
"data.triggers.applyFilterDescription": "Lorsque le filtre Kibana est appliqué. Peut être un filtre simple ou un filtre de plage.",
"data.triggers.applyFilterTitle": "Appliquer le filtre",
+ "unifiedSearch.search.unableToGetSavedQueryToastTitle": "Impossible de charger la requête enregistrée {savedQueryId}",
+ "unifiedSearch.noDataPopover.content": "Cette plage temporelle ne contient pas de données. Étendez ou ajustez la plage temporelle pour obtenir plus de champs et pouvoir créer des graphiques.",
+ "unifiedSearch.noDataPopover.dismissAction": "Ne plus afficher",
+ "unifiedSearch.noDataPopover.subtitle": "Conseil",
+ "unifiedSearch.noDataPopover.title": "Ensemble de données vide",
+ "unifiedSearch.query.queryBar.clearInputLabel": "Effacer l'entrée",
+ "unifiedSearch.query.queryBar.comboboxAriaLabel": "Rechercher et filtrer la page {pageType}",
+ "unifiedSearch.query.queryBar.kqlFullLanguageName": "Langage de requête Kibana",
+ "unifiedSearch.query.queryBar.kqlLanguageName": "KQL",
+ "unifiedSearch.query.queryBar.KQLNestedQuerySyntaxInfoDocLinkText": "documents",
+ "unifiedSearch.query.queryBar.KQLNestedQuerySyntaxInfoOptOutText": "Ne plus afficher",
+ "unifiedSearch.query.queryBar.KQLNestedQuerySyntaxInfoText": "Il semblerait que votre requête porte sur un champ imbriqué. Selon le résultat visé, il existe plusieurs façons de construire une syntaxe KQL pour des requêtes imbriquées. Apprenez-en plus avec notre {link}.",
+ "unifiedSearch.query.queryBar.KQLNestedQuerySyntaxInfoTitle": "Syntaxe de requête imbriquée KQL",
+ "unifiedSearch.query.queryBar.kqlOffLabel": "Désactivé",
+ "unifiedSearch.query.queryBar.kqlOnLabel": "Activé",
+ "unifiedSearch.query.queryBar.languageSwitcher.toText": "Passer au langage de requête Kibana pour la recherche",
+ "unifiedSearch.query.queryBar.luceneLanguageName": "Lucene",
+ "unifiedSearch.query.queryBar.searchInputAriaLabel": "Commencer à taper pour rechercher et filtrer la page {pageType}",
+ "unifiedSearch.query.queryBar.searchInputPlaceholder": "Recherche",
+ "unifiedSearch.query.queryBar.syntaxOptionsDescription": "{docsLink} (KQL) offre une syntaxe de requête simplifiée et la prise en charge des champs scriptés. KQL offre également une fonctionnalité de saisie semi-automatique. Si vous désactivez KQL, {nonKqlModeHelpText}.",
+ "unifiedSearch.query.queryBar.syntaxOptionsDescription.nonKqlModeHelpText": "Kibana utilise Lucene.",
+ "unifiedSearch.search.searchBar.savedQueryDescriptionLabelText": "Description",
+ "unifiedSearch.search.searchBar.savedQueryDescriptionText": "Enregistrez le texte et les filtres de la requête que vous souhaitez réutiliser.",
+ "unifiedSearch.search.searchBar.savedQueryForm.titleConflictText": "Ce nom est en conflit avec une requête enregistrée existante.",
+ "unifiedSearch.search.searchBar.savedQueryFormCancelButtonText": "Annuler",
+ "unifiedSearch.search.searchBar.savedQueryFormSaveButtonText": "Enregistrer",
+ "unifiedSearch.search.searchBar.savedQueryFormTitle": "Enregistrer la requête",
+ "unifiedSearch.search.searchBar.savedQueryIncludeFiltersLabelText": "Inclure les filtres",
+ "unifiedSearch.search.searchBar.savedQueryIncludeTimeFilterLabelText": "Inclure le filtre temporel",
+ "unifiedSearch.search.searchBar.savedQueryNameHelpText": "Un nom est requis. Le nom ne peut pas contenir d'espace vide au début ou à la fin. Le nom doit être unique.",
+ "unifiedSearch.search.searchBar.savedQueryNameLabelText": "Nom",
+ "unifiedSearch.search.searchBar.savedQueryNoSavedQueriesText": "Aucune requête enregistrée.",
+ "unifiedSearch.search.searchBar.savedQueryPopoverButtonText": "Voir les requêtes enregistrées",
+ "unifiedSearch.search.searchBar.savedQueryPopoverClearButtonAriaLabel": "Effacer la requête enregistrée en cours",
+ "unifiedSearch.search.searchBar.savedQueryPopoverClearButtonText": "Effacer",
+ "unifiedSearch.search.searchBar.savedQueryPopoverConfirmDeletionCancelButtonText": "Annuler",
+ "unifiedSearch.search.searchBar.savedQueryPopoverConfirmDeletionConfirmButtonText": "Supprimer",
+ "unifiedSearch.search.searchBar.savedQueryPopoverConfirmDeletionTitle": "Supprimer \"{savedQueryName}\" ?",
+ "unifiedSearch.search.searchBar.savedQueryPopoverDeleteButtonAriaLabel": "Supprimer la requête enregistrée {savedQueryName}",
+ "unifiedSearch.search.searchBar.savedQueryPopoverSaveAsNewButtonAriaLabel": "Enregistrer en tant que nouvelle requête enregistrée",
+ "unifiedSearch.search.searchBar.savedQueryPopoverSaveAsNewButtonText": "Enregistrer en tant que nouvelle",
+ "unifiedSearch.search.searchBar.savedQueryPopoverSaveButtonAriaLabel": "Enregistrer une nouvelle requête enregistrée",
+ "unifiedSearch.search.searchBar.savedQueryPopoverSaveButtonText": "Enregistrer la requête en cours",
+ "unifiedSearch.search.searchBar.savedQueryPopoverSaveChangesButtonAriaLabel": "Enregistrer les modifications apportées à {title}",
+ "unifiedSearch.search.searchBar.savedQueryPopoverSaveChangesButtonText": "Enregistrer les modifications",
+ "unifiedSearch.search.searchBar.savedQueryPopoverSavedQueryListItemButtonAriaLabel": "Bouton de requête enregistrée {savedQueryName}",
+ "unifiedSearch.search.searchBar.savedQueryPopoverSavedQueryListItemDescriptionAriaLabel": "Description de {savedQueryName}",
+ "unifiedSearch.search.searchBar.savedQueryPopoverSavedQueryListItemSelectedButtonAriaLabel": "Bouton de requête enregistrée {savedQueryName} sélectionné. Appuyez pour effacer les modifications.",
+ "unifiedSearch.search.searchBar.savedQueryPopoverTitleText": "Requêtes enregistrées",
+ "unifiedSearch.query.queryBar.syntaxOptionsTitle": "Options de syntaxe",
+ "unifiedSearch.filter.applyFilterActionTitle": "Appliquer le filtre à la vue en cours",
+ "unifiedSearch.filter.applyFilters.popupHeader": "Sélectionner les filtres à appliquer",
+ "unifiedSearch.filter.applyFiltersPopup.cancelButtonLabel": "Annuler",
+ "unifiedSearch.filter.applyFiltersPopup.saveButtonLabel": "Appliquer",
+ "unifiedSearch.filter.filterBar.addFilterButtonLabel": "Ajouter un filtre",
+ "unifiedSearch.filter.filterBar.deleteFilterButtonLabel": "Supprimer",
+ "unifiedSearch.filter.filterBar.disabledFilterPrefix": "Désactivé",
+ "unifiedSearch.filter.filterBar.disableFilterButtonLabel": "Désactiver temporairement",
+ "unifiedSearch.filter.filterBar.editFilterButtonLabel": "Modifier le filtre",
+ "unifiedSearch.filter.filterBar.enableFilterButtonLabel": "Réactiver",
+ "unifiedSearch.filter.filterBar.excludeFilterButtonLabel": "Exclure les résultats",
+ "unifiedSearch.filter.filterBar.filterItemBadgeAriaLabel": "Actions de filtrage",
+ "unifiedSearch.filter.filterBar.filterItemBadgeIconAriaLabel": "Supprimer {filter}",
+ "unifiedSearch.filter.filterBar.includeFilterButtonLabel": "Inclure les résultats",
+ "unifiedSearch.filter.filterBar.indexPatternSelectPlaceholder": "Sélectionner un modèle d'indexation",
+ "unifiedSearch.filter.filterBar.labelErrorInfo": "Modèle d'indexation {indexPattern} introuvable",
+ "unifiedSearch.filter.filterBar.labelErrorText": "Erreur",
+ "unifiedSearch.filter.filterBar.labelWarningInfo": "Le champ {fieldName} n'existe pas dans la vue en cours.",
+ "unifiedSearch.filter.filterBar.labelWarningText": "Avertissement",
+ "unifiedSearch.filter.filterBar.moreFilterActionsMessage": "Filtre : {innerText}. Sélectionner pour plus d’actions de filtrage.",
+ "unifiedSearch.filter.filterBar.negatedFilterPrefix": "NON ",
+ "unifiedSearch.filter.filterBar.pinFilterButtonLabel": "Épingler dans toutes les applications",
+ "unifiedSearch.filter.filterBar.pinnedFilterPrefix": "Épinglé",
+ "unifiedSearch.filter.filterBar.unpinFilterButtonLabel": "Désépingler",
+ "unifiedSearch.filter.filterEditor.cancelButtonLabel": "Annuler",
+ "unifiedSearch.filter.filterEditor.createCustomLabelInputLabel": "Étiquette personnalisée",
+ "unifiedSearch.filter.filterEditor.createCustomLabelSwitchLabel": "Créer une étiquette personnalisée ?",
+ "unifiedSearch.filter.filterEditor.doesNotExistOperatorOptionLabel": "n'existe pas",
+ "unifiedSearch.filter.filterEditor.editFilterPopupTitle": "Modifier le filtre",
+ "unifiedSearch.filter.filterEditor.editFilterValuesButtonLabel": "Modifier les valeurs du filtre",
+ "unifiedSearch.filter.filterEditor.editQueryDslButtonLabel": "Modifier en tant que Query DSL",
+ "unifiedSearch.filter.filterEditor.existsOperatorOptionLabel": "existe",
+ "unifiedSearch.filter.filterEditor.falseOptionLabel": "false",
+ "unifiedSearch.filter.filterEditor.fieldSelectLabel": "Champ",
+ "unifiedSearch.filter.filterEditor.fieldSelectPlaceholder": "Sélectionner d'abord un champ",
+ "unifiedSearch.filter.filterEditor.indexPatternSelectLabel": "Modèle d'indexation",
+ "unifiedSearch.filter.filterEditor.isBetweenOperatorOptionLabel": "est entre",
+ "unifiedSearch.filter.filterEditor.isNotBetweenOperatorOptionLabel": "n'est pas entre",
+ "unifiedSearch.filter.filterEditor.isNotOneOfOperatorOptionLabel": "n'est pas l'une des options suivantes",
+ "unifiedSearch.filter.filterEditor.isNotOperatorOptionLabel": "n'est pas",
+ "unifiedSearch.filter.filterEditor.isOneOfOperatorOptionLabel": "est l'une des options suivantes",
+ "unifiedSearch.filter.filterEditor.isOperatorOptionLabel": "est",
+ "unifiedSearch.filter.filterEditor.operatorSelectLabel": "Opérateur",
+ "unifiedSearch.filter.filterEditor.operatorSelectPlaceholderSelect": "Sélectionner",
+ "unifiedSearch.filter.filterEditor.operatorSelectPlaceholderWaiting": "En attente",
+ "unifiedSearch.filter.filterEditor.queryDslLabel": "Query DSL d'Elasticsearch",
+ "unifiedSearch.filter.filterEditor.rangeEndInputPlaceholder": "Fin de la plage",
+ "unifiedSearch.filter.filterEditor.rangeInputLabel": "Plage",
+ "unifiedSearch.filter.filterEditor.rangeStartInputPlaceholder": "Début de la plage",
+ "unifiedSearch.filter.filterEditor.saveButtonLabel": "Enregistrer",
+ "unifiedSearch.filter.filterEditor.trueOptionLabel": "vrai",
+ "unifiedSearch.filter.filterEditor.valueInputLabel": "Valeur",
+ "unifiedSearch.filter.filterEditor.valueInputPlaceholder": "Saisir une valeur",
+ "unifiedSearch.filter.filterEditor.valueSelectPlaceholder": "Sélectionner une valeur",
+ "unifiedSearch.filter.filterEditor.valuesSelectLabel": "Valeurs",
+ "unifiedSearch.filter.filterEditor.valuesSelectPlaceholder": "Sélectionner des valeurs",
+ "unifiedSearch.filter.options.changeAllFiltersButtonLabel": "Changer tous les filtres",
+ "unifiedSearch.filter.options.deleteAllFiltersButtonLabel": "Tout supprimer",
+ "unifiedSearch.filter.options.disableAllFiltersButtonLabel": "Tout désactiver",
+ "unifiedSearch.filter.options.enableAllFiltersButtonLabel": "Tout activer",
+ "unifiedSearch.filter.options.invertDisabledFiltersButtonLabel": "Inverser l’activation/désactivation",
+ "unifiedSearch.filter.options.invertNegatedFiltersButtonLabel": "Inverser l'inclusion",
+ "unifiedSearch.filter.options.pinAllFiltersButtonLabel": "Tout épingler",
+ "unifiedSearch.filter.options.unpinAllFiltersButtonLabel": "Tout désépingler",
+ "unifiedSearch.filter.searchBar.changeAllFiltersTitle": "Changer tous les filtres",
"devTools.badge.readOnly.text": "Lecture seule",
"devTools.badge.readOnly.tooltip": "Enregistrement impossible",
"devTools.devToolsTitle": "Outils de développement",
@@ -19659,7 +19773,6 @@
"xpack.securitySolution.authenticationsTable.rows": "{numRows} {numRows, plural, =0 {ligne} =1 {ligne} other {lignes}}",
"xpack.securitySolution.authenticationsTable.successes": "Réussites",
"xpack.securitySolution.authenticationsTable.uncommonProcessTable": "Processus inhabituels",
- "xpack.securitySolution.authenticationsTable.unit": "{totalCount, plural, =1 {utilisateur} other {utilisateurs}}",
"xpack.securitySolution.authenticationsTable.user": "Utilisateur",
"xpack.securitySolution.authz.mlUnavailable": "Le plug-in de Machine Learning n'est pas disponible. Essayez d'activer le plug-in.",
"xpack.securitySolution.authz.userIsNotMlAdminMessage": "L'utilisateur actuel n'est pas un administrateur de Machine Learning.",
@@ -25413,120 +25526,6 @@
"xpack.watcher.watchActions.webhook.portIsRequiredValidationMessage": "Le port webhook est requis.",
"xpack.watcher.watchActions.webhook.usernameIsRequiredIfPasswordValidationMessage": "Le nom d'utilisateur est requis.",
"xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "Ce champ est requis.",
- "xpack.watcher.watcherDescription": "Détectez les modifications survenant dans vos données en créant, gérant et monitorant des alertes.",
- "unifiedSearch.noDataPopover.content": "Cette plage temporelle ne contient pas de données. Étendez ou ajustez la plage temporelle pour obtenir plus de champs et pouvoir créer des graphiques.",
- "unifiedSearch.noDataPopover.dismissAction": "Ne plus afficher",
- "unifiedSearch.noDataPopover.subtitle": "Conseil",
- "unifiedSearch.noDataPopover.title": "Ensemble de données vide",
- "unifiedSearch.query.queryBar.clearInputLabel": "Effacer l'entrée",
- "unifiedSearch.query.queryBar.comboboxAriaLabel": "Rechercher et filtrer la page {pageType}",
- "unifiedSearch.query.queryBar.kqlFullLanguageName": "Langage de requête Kibana",
- "unifiedSearch.query.queryBar.kqlLanguageName": "KQL",
- "unifiedSearch.query.queryBar.KQLNestedQuerySyntaxInfoDocLinkText": "documents",
- "unifiedSearch.query.queryBar.KQLNestedQuerySyntaxInfoOptOutText": "Ne plus afficher",
- "unifiedSearch.query.queryBar.KQLNestedQuerySyntaxInfoText": "Il semblerait que votre requête porte sur un champ imbriqué. Selon le résultat visé, il existe plusieurs façons de construire une syntaxe KQL pour des requêtes imbriquées. Apprenez-en plus avec notre {link}.",
- "unifiedSearch.query.queryBar.KQLNestedQuerySyntaxInfoTitle": "Syntaxe de requête imbriquée KQL",
- "unifiedSearch.query.queryBar.kqlOffLabel": "Désactivé",
- "unifiedSearch.query.queryBar.kqlOnLabel": "Activé",
- "unifiedSearch.query.queryBar.languageSwitcher.toText": "Passer au langage de requête Kibana pour la recherche",
- "unifiedSearch.query.queryBar.luceneLanguageName": "Lucene",
- "unifiedSearch.query.queryBar.searchInputAriaLabel": "Commencer à taper pour rechercher et filtrer la page {pageType}",
- "unifiedSearch.query.queryBar.searchInputPlaceholder": "Recherche",
- "unifiedSearch.query.queryBar.syntaxOptionsDescription": "{docsLink} (KQL) offre une syntaxe de requête simplifiée et la prise en charge des champs scriptés. KQL offre également une fonctionnalité de saisie semi-automatique. Si vous désactivez KQL, {nonKqlModeHelpText}.",
- "unifiedSearch.query.queryBar.syntaxOptionsDescription.nonKqlModeHelpText": "Kibana utilise Lucene.",
- "unifiedSearch.search.searchBar.savedQueryDescriptionLabelText": "Description",
- "unifiedSearch.search.searchBar.savedQueryDescriptionText": "Enregistrez le texte et les filtres de la requête que vous souhaitez réutiliser.",
- "unifiedSearch.search.searchBar.savedQueryForm.titleConflictText": "Ce nom est en conflit avec une requête enregistrée existante.",
- "unifiedSearch.search.searchBar.savedQueryFormCancelButtonText": "Annuler",
- "unifiedSearch.search.searchBar.savedQueryFormSaveButtonText": "Enregistrer",
- "unifiedSearch.search.searchBar.savedQueryFormTitle": "Enregistrer la requête",
- "unifiedSearch.search.searchBar.savedQueryIncludeFiltersLabelText": "Inclure les filtres",
- "unifiedSearch.search.searchBar.savedQueryIncludeTimeFilterLabelText": "Inclure le filtre temporel",
- "unifiedSearch.search.searchBar.savedQueryNameHelpText": "Un nom est requis. Le nom ne peut pas contenir d'espace vide au début ou à la fin. Le nom doit être unique.",
- "unifiedSearch.search.searchBar.savedQueryNameLabelText": "Nom",
- "unifiedSearch.search.searchBar.savedQueryNoSavedQueriesText": "Aucune requête enregistrée.",
- "unifiedSearch.search.searchBar.savedQueryPopoverButtonText": "Voir les requêtes enregistrées",
- "unifiedSearch.search.searchBar.savedQueryPopoverClearButtonAriaLabel": "Effacer la requête enregistrée en cours",
- "unifiedSearch.search.searchBar.savedQueryPopoverClearButtonText": "Effacer",
- "unifiedSearch.search.searchBar.savedQueryPopoverConfirmDeletionCancelButtonText": "Annuler",
- "unifiedSearch.search.searchBar.savedQueryPopoverConfirmDeletionConfirmButtonText": "Supprimer",
- "unifiedSearch.search.searchBar.savedQueryPopoverConfirmDeletionTitle": "Supprimer \"{savedQueryName}\" ?",
- "unifiedSearch.search.searchBar.savedQueryPopoverDeleteButtonAriaLabel": "Supprimer la requête enregistrée {savedQueryName}",
- "unifiedSearch.search.searchBar.savedQueryPopoverSaveAsNewButtonAriaLabel": "Enregistrer en tant que nouvelle requête enregistrée",
- "unifiedSearch.search.searchBar.savedQueryPopoverSaveAsNewButtonText": "Enregistrer en tant que nouvelle",
- "unifiedSearch.search.searchBar.savedQueryPopoverSaveButtonAriaLabel": "Enregistrer une nouvelle requête enregistrée",
- "unifiedSearch.search.searchBar.savedQueryPopoverSaveButtonText": "Enregistrer la requête en cours",
- "unifiedSearch.search.searchBar.savedQueryPopoverSaveChangesButtonAriaLabel": "Enregistrer les modifications apportées à {title}",
- "unifiedSearch.search.searchBar.savedQueryPopoverSaveChangesButtonText": "Enregistrer les modifications",
- "unifiedSearch.search.searchBar.savedQueryPopoverSavedQueryListItemButtonAriaLabel": "Bouton de requête enregistrée {savedQueryName}",
- "unifiedSearch.search.searchBar.savedQueryPopoverSavedQueryListItemDescriptionAriaLabel": "Description de {savedQueryName}",
- "unifiedSearch.search.searchBar.savedQueryPopoverSavedQueryListItemSelectedButtonAriaLabel": "Bouton de requête enregistrée {savedQueryName} sélectionné. Appuyez pour effacer les modifications.",
- "unifiedSearch.search.searchBar.savedQueryPopoverTitleText": "Requêtes enregistrées",
- "unifiedSearch.query.queryBar.syntaxOptionsTitle": "Options de syntaxe",
- "unifiedSearch.filter.applyFilterActionTitle": "Appliquer le filtre à la vue en cours",
- "unifiedSearch.filter.applyFilters.popupHeader": "Sélectionner les filtres à appliquer",
- "unifiedSearch.filter.applyFiltersPopup.cancelButtonLabel": "Annuler",
- "unifiedSearch.filter.applyFiltersPopup.saveButtonLabel": "Appliquer",
- "unifiedSearch.filter.filterBar.addFilterButtonLabel": "Ajouter un filtre",
- "unifiedSearch.filter.filterBar.deleteFilterButtonLabel": "Supprimer",
- "unifiedSearch.filter.filterBar.disabledFilterPrefix": "Désactivé",
- "unifiedSearch.filter.filterBar.disableFilterButtonLabel": "Désactiver temporairement",
- "unifiedSearch.filter.filterBar.editFilterButtonLabel": "Modifier le filtre",
- "unifiedSearch.filter.filterBar.enableFilterButtonLabel": "Réactiver",
- "unifiedSearch.filter.filterBar.excludeFilterButtonLabel": "Exclure les résultats",
- "unifiedSearch.filter.filterBar.filterItemBadgeAriaLabel": "Actions de filtrage",
- "unifiedSearch.filter.filterBar.filterItemBadgeIconAriaLabel": "Supprimer {filter}",
- "unifiedSearch.filter.filterBar.includeFilterButtonLabel": "Inclure les résultats",
- "unifiedSearch.filter.filterBar.indexPatternSelectPlaceholder": "Sélectionner un modèle d'indexation",
- "unifiedSearch.filter.filterBar.labelErrorInfo": "Modèle d'indexation {indexPattern} introuvable",
- "unifiedSearch.filter.filterBar.labelErrorText": "Erreur",
- "unifiedSearch.filter.filterBar.labelWarningInfo": "Le champ {fieldName} n'existe pas dans la vue en cours.",
- "unifiedSearch.filter.filterBar.labelWarningText": "Avertissement",
- "unifiedSearch.filter.filterBar.moreFilterActionsMessage": "Filtre : {innerText}. Sélectionner pour plus d’actions de filtrage.",
- "unifiedSearch.filter.filterBar.negatedFilterPrefix": "NON ",
- "unifiedSearch.filter.filterBar.pinFilterButtonLabel": "Épingler dans toutes les applications",
- "unifiedSearch.filter.filterBar.pinnedFilterPrefix": "Épinglé",
- "unifiedSearch.filter.filterBar.unpinFilterButtonLabel": "Désépingler",
- "unifiedSearch.filter.filterEditor.cancelButtonLabel": "Annuler",
- "unifiedSearch.filter.filterEditor.createCustomLabelInputLabel": "Étiquette personnalisée",
- "unifiedSearch.filter.filterEditor.createCustomLabelSwitchLabel": "Créer une étiquette personnalisée ?",
- "unifiedSearch.filter.filterEditor.doesNotExistOperatorOptionLabel": "n'existe pas",
- "unifiedSearch.filter.filterEditor.editFilterPopupTitle": "Modifier le filtre",
- "unifiedSearch.filter.filterEditor.editFilterValuesButtonLabel": "Modifier les valeurs du filtre",
- "unifiedSearch.filter.filterEditor.editQueryDslButtonLabel": "Modifier en tant que Query DSL",
- "unifiedSearch.filter.filterEditor.existsOperatorOptionLabel": "existe",
- "unifiedSearch.filter.filterEditor.falseOptionLabel": "false",
- "unifiedSearch.filter.filterEditor.fieldSelectLabel": "Champ",
- "unifiedSearch.filter.filterEditor.fieldSelectPlaceholder": "Sélectionner d'abord un champ",
- "unifiedSearch.filter.filterEditor.indexPatternSelectLabel": "Modèle d'indexation",
- "unifiedSearch.filter.filterEditor.isBetweenOperatorOptionLabel": "est entre",
- "unifiedSearch.filter.filterEditor.isNotBetweenOperatorOptionLabel": "n'est pas entre",
- "unifiedSearch.filter.filterEditor.isNotOneOfOperatorOptionLabel": "n'est pas l'une des options suivantes",
- "unifiedSearch.filter.filterEditor.isNotOperatorOptionLabel": "n'est pas",
- "unifiedSearch.filter.filterEditor.isOneOfOperatorOptionLabel": "est l'une des options suivantes",
- "unifiedSearch.filter.filterEditor.isOperatorOptionLabel": "est",
- "unifiedSearch.filter.filterEditor.operatorSelectLabel": "Opérateur",
- "unifiedSearch.filter.filterEditor.operatorSelectPlaceholderSelect": "Sélectionner",
- "unifiedSearch.filter.filterEditor.operatorSelectPlaceholderWaiting": "En attente",
- "unifiedSearch.filter.filterEditor.queryDslLabel": "Query DSL d'Elasticsearch",
- "unifiedSearch.filter.filterEditor.rangeEndInputPlaceholder": "Fin de la plage",
- "unifiedSearch.filter.filterEditor.rangeInputLabel": "Plage",
- "unifiedSearch.filter.filterEditor.rangeStartInputPlaceholder": "Début de la plage",
- "unifiedSearch.filter.filterEditor.saveButtonLabel": "Enregistrer",
- "unifiedSearch.filter.filterEditor.trueOptionLabel": "vrai",
- "unifiedSearch.filter.filterEditor.valueInputLabel": "Valeur",
- "unifiedSearch.filter.filterEditor.valueInputPlaceholder": "Saisir une valeur",
- "unifiedSearch.filter.filterEditor.valueSelectPlaceholder": "Sélectionner une valeur",
- "unifiedSearch.filter.filterEditor.valuesSelectLabel": "Valeurs",
- "unifiedSearch.filter.filterEditor.valuesSelectPlaceholder": "Sélectionner des valeurs",
- "unifiedSearch.filter.options.changeAllFiltersButtonLabel": "Changer tous les filtres",
- "unifiedSearch.filter.options.deleteAllFiltersButtonLabel": "Tout supprimer",
- "unifiedSearch.filter.options.disableAllFiltersButtonLabel": "Tout désactiver",
- "unifiedSearch.filter.options.enableAllFiltersButtonLabel": "Tout activer",
- "unifiedSearch.filter.options.invertDisabledFiltersButtonLabel": "Inverser l’activation/désactivation",
- "unifiedSearch.filter.options.invertNegatedFiltersButtonLabel": "Inverser l'inclusion",
- "unifiedSearch.filter.options.pinAllFiltersButtonLabel": "Tout épingler",
- "unifiedSearch.filter.options.unpinAllFiltersButtonLabel": "Tout désépingler",
- "unifiedSearch.filter.searchBar.changeAllFiltersTitle": "Changer tous les filtres"
+ "xpack.watcher.watcherDescription": "Détectez les modifications survenant dans vos données en créant, gérant et monitorant des alertes."
}
}
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 641d7debc580e..45eff378b56f9 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -22595,7 +22595,6 @@
"xpack.securitySolution.authenticationsTable.rows": "{numRows} {numRows, plural, other {行}}",
"xpack.securitySolution.authenticationsTable.successes": "成功",
"xpack.securitySolution.authenticationsTable.uncommonProcessTable": "非共通プロセス",
- "xpack.securitySolution.authenticationsTable.unit": "{totalCount, plural, other {ユーザー}}",
"xpack.securitySolution.authenticationsTable.user": "ユーザー",
"xpack.securitySolution.authz.mlUnavailable": "機械学習プラグインが使用できません。プラグインを有効にしてください。",
"xpack.securitySolution.authz.userIsNotMlAdminMessage": "現在のユーザーは機械学習管理者ではありません。",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 059e2f68cd5f2..ff9dfba86005e 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -22622,7 +22622,6 @@
"xpack.securitySolution.authenticationsTable.rows": "{numRows} {numRows, plural, other {行}}",
"xpack.securitySolution.authenticationsTable.successes": "成功",
"xpack.securitySolution.authenticationsTable.uncommonProcessTable": "不常见进程",
- "xpack.securitySolution.authenticationsTable.unit": "{totalCount, plural, other {个用户}}",
"xpack.securitySolution.authenticationsTable.user": "用户",
"xpack.securitySolution.authz.mlUnavailable": "Machine Learning 插件不可用。请尝试启用插件。",
"xpack.securitySolution.authz.userIsNotMlAdminMessage": "当前用户不是 Machine Learning 管理员。",
diff --git a/x-pack/test/security_solution_cypress/es_archives/users/data.json b/x-pack/test/security_solution_cypress/es_archives/users/data.json
index d56e7b0ed8d15..b52ff2780252e 100644
--- a/x-pack/test/security_solution_cypress/es_archives/users/data.json
+++ b/x-pack/test/security_solution_cypress/es_archives/users/data.json
@@ -29,6 +29,9 @@
},
"name" : "test"
},
+ "host": {
+ "name": "test-host"
+ },
"service" : {
"type" : "system"
},
@@ -70,6 +73,9 @@
},
"name" : "test"
},
+ "host": {
+ "name": "test-host"
+ },
"service" : {
"type" : "system"
},
From b239151646c8463ac5d0d0b271f15596406d27e2 Mon Sep 17 00:00:00 2001
From: Joe Reuter
Date: Mon, 11 Apr 2022 17:54:57 +0200
Subject: [PATCH 04/75] Handle empty values for range formatters (#129572)
---
.../aggs/utils/get_aggs_formats.test.ts | 21 ++++++++
.../search/aggs/utils/get_aggs_formats.ts | 12 +++++
.../public/components/table_vis_columns.tsx | 50 +++++++++----------
3 files changed, 56 insertions(+), 27 deletions(-)
diff --git a/src/plugins/data/common/search/aggs/utils/get_aggs_formats.test.ts b/src/plugins/data/common/search/aggs/utils/get_aggs_formats.test.ts
index 963fe024c1f8f..c8d173461cf3b 100644
--- a/src/plugins/data/common/search/aggs/utils/get_aggs_formats.test.ts
+++ b/src/plugins/data/common/search/aggs/utils/get_aggs_formats.test.ts
@@ -49,6 +49,13 @@ describe('getAggsFormats', () => {
expect(getFormat).toHaveBeenCalledTimes(3);
});
+ test('date_range does not crash on empty value', () => {
+ const mapping = { id: 'date_range', params: {} };
+ const format = getAggFormat(mapping, getFormat);
+
+ expect(format.convert(undefined)).toBe('');
+ });
+
test('creates custom format for ip_range', () => {
const mapping = { id: 'ip_range', params: {} };
const format = getAggFormat(mapping, getFormat);
@@ -62,6 +69,13 @@ describe('getAggsFormats', () => {
expect(getFormat).toHaveBeenCalledTimes(4);
});
+ test('ip_range does not crash on empty value', () => {
+ const mapping = { id: 'ip_range', params: {} };
+ const format = getAggFormat(mapping, getFormat);
+
+ expect(format.convert(undefined)).toBe('');
+ });
+
test('creates custom format for range', () => {
const mapping = { id: 'range', params: {} };
const format = getAggFormat(mapping, getFormat);
@@ -70,6 +84,13 @@ describe('getAggsFormats', () => {
expect(getFormat).toHaveBeenCalledTimes(1);
});
+ test('range does not crash on empty value', () => {
+ const mapping = { id: 'range', params: {} };
+ const format = getAggFormat(mapping, getFormat);
+
+ expect(format.convert(undefined)).toBe('');
+ });
+
test('creates alternative format for range using the template parameter', () => {
const mapping = { id: 'range', params: { template: 'arrow_right' } };
const format = getAggFormat(mapping, getFormat);
diff --git a/src/plugins/data/common/search/aggs/utils/get_aggs_formats.ts b/src/plugins/data/common/search/aggs/utils/get_aggs_formats.ts
index 876d7673b87a6..2233c9338cd58 100644
--- a/src/plugins/data/common/search/aggs/utils/get_aggs_formats.ts
+++ b/src/plugins/data/common/search/aggs/utils/get_aggs_formats.ts
@@ -44,6 +44,10 @@ export function getAggsFormats(getFieldFormat: GetFieldFormat): FieldFormatInsta
textConvert = (range: any) => {
const params = this._params;
+ if (range == null) {
+ return '';
+ }
+
if (range.label) {
return range.label;
}
@@ -90,6 +94,10 @@ export function getAggsFormats(getFieldFormat: GetFieldFormat): FieldFormatInsta
static hidden = true;
textConvert = (range: DateRange) => {
+ if (range == null) {
+ return '';
+ }
+
const nestedFormatter = this._params as SerializedFieldFormat;
const format = getFieldFormat({
id: nestedFormatter.id,
@@ -103,6 +111,10 @@ export function getAggsFormats(getFieldFormat: GetFieldFormat): FieldFormatInsta
static hidden = true;
textConvert = (range: IpRangeKey) => {
+ if (range == null) {
+ return '';
+ }
+
const nestedFormatter = this._params as SerializedFieldFormat;
const format = getFieldFormat({
id: nestedFormatter.id,
diff --git a/src/plugins/vis_types/table/public/components/table_vis_columns.tsx b/src/plugins/vis_types/table/public/components/table_vis_columns.tsx
index 2abeae31fbea9..17d32264998ea 100644
--- a/src/plugins/vis_types/table/public/components/table_vis_columns.tsx
+++ b/src/plugins/vis_types/table/public/components/table_vis_columns.tsx
@@ -57,7 +57,7 @@ export const createGridColumns = (
? [
({ rowIndex, columnId, Component, closePopover }: EuiDataGridColumnCellActionProps) => {
const rowValue = rows[rowIndex][columnId];
- const contentsIsDefined = rowValue !== null && rowValue !== undefined;
+ if (rowValue == null) return null;
const cellContent = formattedColumn.formatter.convert(rowValue);
const filterForText = i18n.translate(
@@ -77,24 +77,22 @@ export const createGridColumns = (
);
return (
- contentsIsDefined && (
- {
- onFilterClick({ row: rowIndex, column: colIndex, value: rowValue }, false);
- closePopover?.();
- }}
- iconType="plusInCircle"
- >
- {filterForText}
-
- )
+ {
+ onFilterClick({ row: rowIndex, column: colIndex, value: rowValue }, false);
+ closePopover?.();
+ }}
+ iconType="plusInCircle"
+ >
+ {filterForText}
+
);
},
({ rowIndex, columnId, Component, closePopover }: EuiDataGridColumnCellActionProps) => {
const rowValue = rows[rowIndex][columnId];
- const contentsIsDefined = rowValue !== null && rowValue !== undefined;
+ if (rowValue == null) return null;
const cellContent = formattedColumn.formatter.convert(rowValue);
const filterOutText = i18n.translate(
@@ -114,18 +112,16 @@ export const createGridColumns = (
);
return (
- contentsIsDefined && (
- {
- onFilterClick({ row: rowIndex, column: colIndex, value: rowValue }, true);
- closePopover?.();
- }}
- iconType="minusInCircle"
- >
- {filterOutText}
-
- )
+ {
+ onFilterClick({ row: rowIndex, column: colIndex, value: rowValue }, true);
+ closePopover?.();
+ }}
+ iconType="minusInCircle"
+ >
+ {filterOutText}
+
);
},
]
From 6e8d97948a2acf5d6989efe88da2a1f01d39b8a0 Mon Sep 17 00:00:00 2001
From: Cristina Amico
Date: Mon, 11 Apr 2022 18:11:27 +0200
Subject: [PATCH 05/75] [Fleet] Redesign agent flyout (#128381)
* [Fleet] Redesign and refactor agent flyout
* Further refactoring
* More refactoring and some bug fixing
* bug fixing
* Fix step tests + skip standalone tab tests
* Use test-subj for agent policy code block to fix cypress tests
* Fixing small issues on rendering
* Fix broken import; Fix button in incoming data comp
* Fix loading; add button in incoming data step
* Fix some failures
* Fix tests
* Fix checks
* Address code review comments; add retry logic to incoming data component
* Fix download link
* Check enrolled agents in last 10 minutes
* Filter out agents with data=false from incoming data
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Kyle Pollich
---
.../cypress/integration/fleet_startup.spec.ts | 7 +-
x-pack/plugins/fleet/cypress/screens/fleet.ts | 1 +
x-pack/plugins/fleet/cypress/tasks/fleet.ts | 1 -
.../fleet_server_on_prem_instructions.tsx | 67 ++--
.../fleet/sections/agents/index.tsx | 1 +
.../detail/policies/package_policies.tsx | 75 +---
.../agent_enrollment_flyout.test.mocks.ts | 34 +-
.../agent_enrollment_flyout.test.tsx | 90 ++---
.../agent_policy_select_create.tsx | 55 ++-
.../agent_policy_selection.test.tsx | 11 +-
.../agent_policy_selection.tsx | 55 ++-
.../confirm_agent_enrollment.tsx | 102 ++++-
.../confirm_incoming_data.tsx | 97 ++---
.../default_missing_requirements.tsx | 35 ++
.../agent_enrollment_flyout/hooks.tsx | 7 +-
.../agent_enrollment_flyout/index.tsx | 135 ++++---
.../installation_message.tsx | 59 +++
.../agent_enrollment_flyout/instructions.tsx | 126 ++++++
.../managed_instructions.tsx | 206 ----------
.../standalone_instructions.tsx | 281 -------------
.../agent_enrollment_confirmation_step.tsx | 41 ++
.../agent_enrollment_key_selection_step.tsx | 53 +++
.../steps/agent_policy_selection_step.tsx | 54 +++
.../steps/compute_steps.tsx | 369 ++++++++++++++++++
.../steps/configure_standalone_agent_step.tsx | 116 ++++++
.../{steps.tsx => steps/download_step.tsx} | 110 +-----
.../steps/incoming_data_confirmation_step.tsx | 47 +++
.../agent_enrollment_flyout/steps/index.tsx | 17 +
.../steps/install_managed_agent_step.tsx | 41 ++
.../steps/install_standalone_agent_step.tsx | 47 +++
.../installation_mode_selection_step.tsx | 88 +++++
.../agent_enrollment_flyout/types.ts | 39 +-
.../use_get_agent_incoming_data.tsx | 121 ++++++
.../enrollment_instructions/manual/index.tsx | 27 +-
.../manual/platform_selector.tsx | 28 +-
.../standalone/index.tsx | 51 +++
.../package_policy_actions_menu.tsx | 10 +-
x-pack/plugins/fleet/public/hooks/index.ts | 1 -
.../hooks/use_get_agent_incoming_data.tsx | 78 ----
.../fleet/public/hooks/use_platform.tsx | 2 +-
.../fleet/server/services/agents/status.ts | 2 +-
.../translations/translations/fr-FR.json | 10 -
.../translations/translations/ja-JP.json | 10 -
.../translations/translations/zh-CN.json | 10 -
44 files changed, 1704 insertions(+), 1113 deletions(-)
create mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/default_missing_requirements.tsx
create mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/installation_message.tsx
create mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/instructions.tsx
delete mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/managed_instructions.tsx
delete mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/standalone_instructions.tsx
create mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_enrollment_confirmation_step.tsx
create mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_enrollment_key_selection_step.tsx
create mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_policy_selection_step.tsx
create mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/compute_steps.tsx
create mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/configure_standalone_agent_step.tsx
rename x-pack/plugins/fleet/public/components/agent_enrollment_flyout/{steps.tsx => steps/download_step.tsx} (67%)
create mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/incoming_data_confirmation_step.tsx
create mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/index.tsx
create mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/install_managed_agent_step.tsx
create mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/install_standalone_agent_step.tsx
create mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/installation_mode_selection_step.tsx
create mode 100644 x-pack/plugins/fleet/public/components/agent_enrollment_flyout/use_get_agent_incoming_data.tsx
create mode 100644 x-pack/plugins/fleet/public/components/enrollment_instructions/standalone/index.tsx
delete mode 100644 x-pack/plugins/fleet/public/hooks/use_get_agent_incoming_data.tsx
diff --git a/x-pack/plugins/fleet/cypress/integration/fleet_startup.spec.ts b/x-pack/plugins/fleet/cypress/integration/fleet_startup.spec.ts
index 1505754635bcb..4f7f4378c0fc2 100644
--- a/x-pack/plugins/fleet/cypress/integration/fleet_startup.spec.ts
+++ b/x-pack/plugins/fleet/cypress/integration/fleet_startup.spec.ts
@@ -10,6 +10,7 @@ import {
ADD_AGENT_BUTTON_TOP,
AGENT_FLYOUT_CLOSE_BUTTON,
STANDALONE_TAB,
+ AGENT_POLICY_CODE_BLOCK,
} from '../screens/fleet';
import { cleanupAgentPolicies, unenrollAgent } from '../tasks/cleanup';
import { verifyPolicy, verifyAgentPackage, navigateToTab } from '../tasks/fleet';
@@ -60,12 +61,11 @@ describe('Fleet startup', () => {
cy.log('Create agent policy took: ' + (Date.now() - startTime) / 1000 + ' s');
agentPolicyId = xhr.response.body.item.id;
- cy.getBySel('agentPolicyCreateStatusCallOut').contains('Agent policy created');
-
// verify create button changed to dropdown
cy.getBySel('agentPolicyDropdown');
+
// verify agent.yml code block has new policy id
- cy.get('.euiCodeBlock__code').contains(`id: ${agentPolicyId}`);
+ cy.getBySel(AGENT_POLICY_CODE_BLOCK).contains(`id: ${agentPolicyId}`);
cy.getBySel(AGENT_FLYOUT_CLOSE_BUTTON).click();
@@ -78,7 +78,6 @@ describe('Fleet startup', () => {
it('should create Fleet Server policy', () => {
cy.getBySel('createFleetServerPolicyBtn').click();
- cy.getBySel('agentPolicyCreateStatusCallOut').contains('Agent policy created');
// verify policy is created and has fleet server and system package
verifyPolicy('Fleet Server policy 1', ['Fleet Server', 'System']);
diff --git a/x-pack/plugins/fleet/cypress/screens/fleet.ts b/x-pack/plugins/fleet/cypress/screens/fleet.ts
index 32ecdc4f5da71..ef3389b90bd5d 100644
--- a/x-pack/plugins/fleet/cypress/screens/fleet.ts
+++ b/x-pack/plugins/fleet/cypress/screens/fleet.ts
@@ -9,6 +9,7 @@ export const ADD_AGENT_BUTTON = 'addAgentButton';
export const ADD_AGENT_BUTTON_TOP = 'addAgentBtnTop';
export const CREATE_POLICY_BUTTON = 'createPolicyBtn';
export const AGENT_FLYOUT_CLOSE_BUTTON = 'euiFlyoutCloseButton';
+export const AGENT_POLICY_CODE_BLOCK = 'agentPolicyCodeBlock';
export const AGENTS_TAB = 'fleet-agents-tab';
export const AGENT_POLICIES_TAB = 'fleet-agent-policies-tab';
diff --git a/x-pack/plugins/fleet/cypress/tasks/fleet.ts b/x-pack/plugins/fleet/cypress/tasks/fleet.ts
index 304ab7445d4e4..926734503ae0c 100644
--- a/x-pack/plugins/fleet/cypress/tasks/fleet.ts
+++ b/x-pack/plugins/fleet/cypress/tasks/fleet.ts
@@ -18,7 +18,6 @@ export function createAgentPolicy() {
cy.getBySel(ADD_AGENT_BUTTON_TOP).click();
cy.getBySel(STANDALONE_TAB).click();
cy.getBySel(CREATE_POLICY_BUTTON).click();
- cy.getBySel('agentPolicyCreateStatusCallOut').contains('Agent policy created');
cy.getBySel(AGENT_FLYOUT_CLOSE_BUTTON).click();
}
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/components/fleet_server_on_prem_instructions.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/components/fleet_server_on_prem_instructions.tsx
index 1eef74180fdd3..93547bba36de8 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/components/fleet_server_on_prem_instructions.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/components/fleet_server_on_prem_instructions.tsx
@@ -203,7 +203,6 @@ export const FleetServerCommandStep = ({
windowsCommand={installCommand.windows}
linuxDebCommand={installCommand.deb}
linuxRpmCommand={installCommand.rpm}
- troubleshootLink={docLinks.links.fleet.troubleshooting}
isK8s={false}
/>
>
@@ -290,36 +289,16 @@ export const useFleetServerInstructions = (policyId?: string) => {
};
const AgentPolicySelectionStep = ({
- policyId,
+ selectedPolicy,
setPolicyId,
+ agentPolicies,
+ refreshAgentPolicies,
}: {
- policyId?: string;
- setPolicyId: (v: string) => void;
+ selectedPolicy?: AgentPolicy;
+ setPolicyId: (v?: string) => void;
+ agentPolicies: AgentPolicy[];
+ refreshAgentPolicies: () => void;
}): EuiStepProps => {
- const { data, resendRequest: refreshAgentPolicies } = useGetAgentPolicies({ full: true });
-
- const agentPolicies = useMemo(
- () => (data ? data.items.filter((item) => policyHasFleetServer(item)) : []),
- [data]
- );
-
- useEffect(() => {
- // Select default value
- if (agentPolicies.length && !policyId) {
- setPolicyId(agentPolicies[0].id);
- }
- }, [agentPolicies, policyId, setPolicyId]);
-
- const onChangeCallback = useCallback(
- (key: string | undefined, policy?: AgentPolicy) => {
- if (policy) {
- refreshAgentPolicies();
- }
- setPolicyId(key!);
- },
- [setPolicyId, refreshAgentPolicies]
- );
-
return {
title:
agentPolicies.length === 0
@@ -335,9 +314,11 @@ const AgentPolicySelectionStep = ({
>
),
@@ -642,9 +623,28 @@ const CompleteStep = (): EuiStepProps => {
};
};
+const findPolicyById = (policies: AgentPolicy[], id: string | undefined) => {
+ if (!id) return undefined;
+ return policies.find((p) => p.id === id);
+};
+
export const OnPremInstructions: React.FC = () => {
const { notifications } = useStartServices();
- const [policyId, setPolicyId] = useState();
+
+ const { data, resendRequest: refreshAgentPolicies } = useGetAgentPolicies({ full: true });
+
+ const agentPolicies = useMemo(
+ () => (data ? data.items.filter((item) => policyHasFleetServer(item)) : []),
+ [data]
+ );
+
+ // Select default value
+ let defaultValue = '';
+ if (agentPolicies.length) {
+ defaultValue = agentPolicies[0].id;
+ }
+ const [policyId, setPolicyId] = useState(defaultValue);
+ const selectedPolicy = findPolicyById(agentPolicies, policyId);
const {
serviceToken,
@@ -720,7 +720,12 @@ export const OnPremInstructions: React.FC = () => {
{
setIsEnrollmentFlyoutOpen(false)}
/>
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx
index 7ca852fa9b6e7..3edb60ff10a48 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx
@@ -7,11 +7,7 @@
import { stringify, parse } from 'query-string';
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
import { Redirect, useLocation, useHistory } from 'react-router-dom';
-import type {
- CriteriaWithPagination,
- EuiStepProps,
- EuiTableFieldDataColumnType,
-} from '@elastic/eui';
+import type { CriteriaWithPagination, EuiTableFieldDataColumnType } from '@elastic/eui';
import {
EuiBasicTable,
EuiLink,
@@ -19,7 +15,6 @@ import {
EuiFlexItem,
EuiText,
EuiButton,
- EuiSpacer,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedRelative, FormattedMessage } from '@kbn/i18n-react';
@@ -31,7 +26,6 @@ import {
useUrlPagination,
useGetPackageInstallStatus,
AgentPolicyRefreshContext,
- useUIExtension,
usePackageInstallations,
useAuthz,
} from '../../../../../hooks';
@@ -103,7 +97,6 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name: ${name}`,
});
const { updatableIntegrations } = usePackageInstallations();
- const agentEnrollmentFlyoutExtension = useUIExtension(name, 'agent-enrollment-flyout');
const canWriteIntegrationPolicies = useAuthz().integrations.writeIntegrationPolicies;
@@ -165,50 +158,6 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
[setPagination]
);
- const viewDataStep = useMemo(() => {
- if (agentEnrollmentFlyoutExtension) {
- return {
- title: agentEnrollmentFlyoutExtension.title,
- children: ,
- };
- }
-
- return {
- title: i18n.translate('xpack.fleet.agentEnrollment.stepViewDataTitle', {
- defaultMessage: 'View your data',
- }),
- children: (
- <>
-
-
- {i18n.translate(
- 'xpack.fleet.epm.agentEnrollment.viewDataDescription.pleaseNoteLabel',
- { defaultMessage: 'Please note' }
- )}
-
- ),
- }}
- />
-
-
-
- {i18n.translate('xpack.fleet.epm.agentEnrollment.viewDataAssetsLabel', {
- defaultMessage: 'View assets',
- })}
-
- >
- ),
- };
- }, [name, version, getHref, agentEnrollmentFlyoutExtension]);
-
const columns: Array> = useMemo(
() => [
{
@@ -323,7 +272,6 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
{
@@ -362,6 +310,11 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
);
}
+ const selectedPolicies = packageAndAgentPolicies.find(
+ ({ agentPolicy: policy }) => policy.id === flyoutOpenForPolicyId
+ );
+ const agentPolicy = selectedPolicies?.agentPolicy;
+ const packagePolicy = selectedPolicies?.packagePolicy;
return (
@@ -379,19 +332,19 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
/>
- {flyoutOpenForPolicyId && !isLoading && (
+ {flyoutOpenForPolicyId && agentPolicy && !isLoading && (
{
setFlyoutOpenForPolicyId(null);
const { addAgentToPolicyId, ...rest } = parse(search);
history.replace({ search: stringify(rest) });
}}
- agentPolicy={
- packageAndAgentPolicies.find(
- ({ agentPolicy }) => agentPolicy.id === flyoutOpenForPolicyId
- )?.agentPolicy
- }
- viewDataStep={viewDataStep}
+ agentPolicy={agentPolicy}
+ isIntegrationFlow={true}
+ installedPackagePolicy={{
+ name: packagePolicy?.package?.name || '',
+ version: packagePolicy?.package?.version || '',
+ }}
/>
)}
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.mocks.ts b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.mocks.ts
index 15f6437485925..408f884116e26 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.mocks.ts
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.mocks.ts
@@ -8,6 +8,7 @@
jest.mock('../../hooks', () => {
return {
...jest.requireActual('../../hooks'),
+ useFleetStatus: jest.fn(),
useAgentEnrollmentFlyoutData: jest.fn(),
};
});
@@ -24,6 +25,16 @@ jest.mock('../../hooks/use_request', () => {
};
});
+jest.mock('../../applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy', () => {
+ const module = jest.requireActual(
+ '../../applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy'
+ );
+ return {
+ ...module,
+ useFleetServerUnhealthy: jest.fn(),
+ };
+});
+
jest.mock(
'../../applications/fleet/sections/agents/agent_requirements_page/components/fleet_server_on_prem_instructions',
() => {
@@ -57,18 +68,17 @@ jest.mock('./steps', () => {
const module = jest.requireActual('./steps');
return {
...module,
- AgentPolicySelectionStep: jest.fn(),
- AgentEnrollmentKeySelectionStep: jest.fn(),
- ViewDataStep: jest.fn(),
- DownloadStep: jest.fn(),
- };
-});
-
-jest.mock('@elastic/eui', () => {
- const module = jest.requireActual('@elastic/eui');
- return {
- ...module,
- EuiSteps: 'eui-steps',
+ AgentPolicySelectionStep: jest.fn().mockReturnValue({
+ 'data-test-subj': 'agent-policy-selection-step',
+ title: 'agent-policy-selection-step',
+ }),
+ AgentEnrollmentKeySelectionStep: jest.fn().mockReturnValue({
+ 'data-test-subj': 'agent-enrollment-key-selection-step',
+ title: 'agent-enrollment-key-selection-step',
+ }),
+ DownloadStep: jest
+ .fn()
+ .mockReturnValue({ 'data-test-subj': 'download-step', title: 'download-step' }),
};
});
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.tsx
index 3629fe43969e4..7a4d1ed44c406 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.tsx
@@ -16,27 +16,23 @@ import { coreMock } from 'src/core/public/mocks';
import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public';
import type { AgentPolicy } from '../../../common';
-import {
- useGetSettings,
- sendGetFleetStatus,
- sendGetOneAgentPolicy,
- useGetAgents,
-} from '../../hooks/use_request';
+import { useGetSettings, sendGetOneAgentPolicy, useGetAgents } from '../../hooks/use_request';
import {
FleetStatusProvider,
ConfigContext,
useAgentEnrollmentFlyoutData,
KibanaVersionContext,
+ useFleetStatus,
} from '../../hooks';
import { useFleetServerInstructions } from '../../applications/fleet/sections/agents/agent_requirements_page/components';
-import { AgentEnrollmentKeySelectionStep, AgentPolicySelectionStep } from './steps';
+import { useFleetServerUnhealthy } from '../../applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy';
-import type { Props } from '.';
+import type { FlyOutProps } from './types';
import { AgentEnrollmentFlyout } from '.';
-const TestComponent = (props: Props) => (
+const TestComponent = (props: FlyOutProps) => (
@@ -48,7 +44,7 @@ const TestComponent = (props: Props) => (
);
-const setup = async (props?: Props) => {
+const setup = async (props?: FlyOutProps) => {
const testBed = await registerTestBed(TestComponent)(props);
const { find, component } = testBed;
@@ -87,8 +83,10 @@ describe('', () => {
data: { item: { fleet_server_hosts: ['test'] } },
});
- (sendGetFleetStatus as jest.Mock).mockResolvedValue({
- data: { isReady: true },
+ (useFleetStatus as jest.Mock).mockReturnValue({ isReady: true });
+ (useFleetServerUnhealthy as jest.Mock).mockReturnValue({
+ isLoading: false,
+ isUnhealthy: false,
});
(sendGetOneAgentPolicy as jest.Mock).mockResolvedValue({
@@ -147,9 +145,10 @@ describe('', () => {
describe('managed instructions', () => {
it('uses the agent policy selection step', async () => {
const { exists } = testBed;
+
expect(exists('agentEnrollmentFlyout')).toBe(true);
- expect(AgentPolicySelectionStep).toHaveBeenCalled();
- expect(AgentEnrollmentKeySelectionStep).not.toHaveBeenCalled();
+ expect(exists('agent-policy-selection-step')).toBe(true);
+ expect(exists('agent-enrollment-key-selection-step')).toBe(false);
});
describe('with a specific policy', () => {
@@ -167,8 +166,8 @@ describe('', () => {
it('uses the configure enrollment step, not the agent policy selection step', () => {
const { exists } = testBed;
expect(exists('agentEnrollmentFlyout')).toBe(true);
- expect(AgentPolicySelectionStep).not.toHaveBeenCalled();
- expect(AgentEnrollmentKeySelectionStep).toHaveBeenCalled();
+ expect(exists('agent-policy-selection-step')).toBe(false);
+ expect(exists('agent-enrollment-key-selection-step')).toBe(true);
});
});
@@ -187,58 +186,21 @@ describe('', () => {
it('should not show fleet server instructions', () => {
const { exists } = testBed;
expect(exists('agentEnrollmentFlyout')).toBe(true);
- expect(AgentEnrollmentKeySelectionStep).toHaveBeenCalled();
- });
- });
-
- // Skipped due to implementation details in the step components. See https://github.com/elastic/kibana/issues/103894
- describe.skip('"View data" extension point', () => {
- it('shows the "View data" step when UI extension is provided', async () => {
- jest.clearAllMocks();
- await act(async () => {
- testBed = await setup({
- onClose: jest.fn(),
- viewDataStep: { title: 'View Data', children: },
- });
- testBed.component.update();
- });
- const { exists, actions } = testBed;
- expect(exists('agentEnrollmentFlyout')).toBe(true);
- expect(exists('view-data-step')).toBe(true);
-
- jest.clearAllMocks();
- actions.goToStandaloneTab();
- expect(exists('agentEnrollmentFlyout')).toBe(true);
- expect(exists('view-data-step')).toBe(false);
- });
-
- it('does not call the "View data" step when UI extension is not provided', async () => {
- jest.clearAllMocks();
- await act(async () => {
- testBed = await setup({
- onClose: jest.fn(),
- viewDataStep: undefined,
- });
- testBed.component.update();
- });
- const { exists, actions } = testBed;
- expect(exists('agentEnrollmentFlyout')).toBe(true);
- expect(exists('view-data-step')).toBe(false);
-
- jest.clearAllMocks();
- actions.goToStandaloneTab();
- expect(exists('view-data-step')).toBe(false);
+ expect(exists('agent-enrollment-key-selection-step')).toBe(true);
});
});
});
- describe('standalone instructions', () => {
+ // Skipped due to UI changing in https://github.com/elastic/kibana/issues/125534. These tests should be rethought overall
+ // to provide value around the new flyout structure
+ describe.skip('standalone instructions', () => {
it('uses the agent policy selection step', async () => {
const { exists, actions } = testBed;
actions.goToStandaloneTab();
+
expect(exists('agentEnrollmentFlyout')).toBe(true);
- expect(AgentPolicySelectionStep).toHaveBeenCalled();
- expect(AgentEnrollmentKeySelectionStep).not.toHaveBeenCalled();
+ expect(exists('agent-policy-selection-step')).toBe(true);
+ expect(exists('agent-enrollment-key-selection-step')).toBe(false);
});
describe('with a specific policy', () => {
@@ -256,10 +218,12 @@ describe('', () => {
it('does not use either of the agent policy selection or enrollment key steps', () => {
const { exists, actions } = testBed;
jest.clearAllMocks();
- expect(exists('agentEnrollmentFlyout')).toBe(true);
+
actions.goToStandaloneTab();
- expect(AgentPolicySelectionStep).not.toHaveBeenCalled();
- expect(AgentEnrollmentKeySelectionStep).not.toHaveBeenCalled();
+
+ expect(exists('agentEnrollmentFlyout')).toBe(true);
+ expect(exists('agent-policy-selection-step')).toBe(false);
+ expect(exists('agent-enrollment-key-selection-step')).toBe(false);
});
});
});
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_select_create.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_select_create.tsx
index 53e8140086c2c..81ec1236920b8 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_select_create.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_select_create.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import React, { useState, useCallback, useEffect } from 'react';
+import React, { useState, useCallback, useEffect, useMemo } from 'react';
import type { AgentPolicyCreateState } from '../../applications/fleet/sections/agents/components';
import {
@@ -16,43 +16,60 @@ import { AgentPolicyCreateInlineForm } from '../../applications/fleet/sections/a
import type { AgentPolicy } from '../../types';
import { incrementPolicyName } from '../../services';
-import { EnrollmentStepAgentPolicy } from '.';
+import { AgentPolicySelection } from '.';
interface Props {
agentPolicies: AgentPolicy[];
+ selectedPolicy?: AgentPolicy;
+ setSelectedPolicyId: (agentPolicyId?: string) => void;
excludeFleetServer?: boolean;
- onAgentPolicyChange: (key?: string, policy?: AgentPolicy) => void;
withKeySelection: boolean;
selectedApiKeyId?: string;
onKeyChange?: (key?: string) => void;
isFleetServerPolicy?: boolean;
- policyId?: string;
+ refreshAgentPolicies: () => void;
}
export const SelectCreateAgentPolicy: React.FC = ({
agentPolicies,
excludeFleetServer,
- onAgentPolicyChange,
+ setSelectedPolicyId,
+ selectedPolicy,
withKeySelection,
selectedApiKeyId,
onKeyChange,
isFleetServerPolicy,
- policyId,
+ refreshAgentPolicies,
}) => {
- const [showCreatePolicy, setShowCreatePolicy] = useState(agentPolicies.length === 0);
+ const regularAgentPolicies = useMemo(() => {
+ return agentPolicies.filter(
+ (policy) =>
+ policy && !policy.is_managed && (!excludeFleetServer || !policy.is_default_fleet_server)
+ );
+ }, [agentPolicies, excludeFleetServer]);
+
+ const onAgentPolicyChange = useCallback(
+ async (key?: string, policy?: AgentPolicy) => {
+ if (policy) {
+ refreshAgentPolicies();
+ }
+ },
+ [refreshAgentPolicies]
+ );
+ const [showCreatePolicy, setShowCreatePolicy] = useState(regularAgentPolicies.length === 0);
const [createState, setCreateState] = useState({
status: CREATE_STATUS.INITIAL,
});
- const [newName, setNewName] = useState(incrementPolicyName(agentPolicies, isFleetServerPolicy));
-
- const [selectedAgentPolicy, setSelectedAgentPolicy] = useState(policyId);
+ const [newName, setNewName] = useState(
+ incrementPolicyName(regularAgentPolicies, isFleetServerPolicy)
+ );
useEffect(() => {
- setShowCreatePolicy(agentPolicies.length === 0);
- setNewName(incrementPolicyName(agentPolicies, isFleetServerPolicy));
- }, [agentPolicies, isFleetServerPolicy]);
+ setShowCreatePolicy(regularAgentPolicies.length === 0);
+ setNewName(incrementPolicyName(regularAgentPolicies, isFleetServerPolicy));
+ }, [regularAgentPolicies, isFleetServerPolicy]);
const onAgentPolicyCreated = useCallback(
async (policy: AgentPolicy | null, errorMessage?: JSX.Element) => {
@@ -65,9 +82,9 @@ export const SelectCreateAgentPolicy: React.FC = ({
if (onAgentPolicyChange) {
onAgentPolicyChange(policy.id, policy!);
}
- setSelectedAgentPolicy(policy.id);
+ setSelectedPolicyId(policy.id);
},
- [onAgentPolicyChange]
+ [setSelectedPolicyId, onAgentPolicyChange]
);
const onClickCreatePolicy = () => {
@@ -87,15 +104,15 @@ export const SelectCreateAgentPolicy: React.FC = ({
agentPolicyName={newName}
/>
) : (
-
)}
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_selection.test.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_selection.test.tsx
index b84d101fdef5f..c5a6076308525 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_selection.test.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_selection.test.tsx
@@ -13,7 +13,7 @@ import { createFleetTestRendererMock } from '../../mock';
import type { AgentPolicy } from '../../types';
-import { EnrollmentStepAgentPolicy } from '.';
+import { AgentPolicySelection } from '.';
describe('step select agent policy', () => {
let testRenderer: TestRenderer;
@@ -21,10 +21,11 @@ describe('step select agent policy', () => {
let agentPolicies: AgentPolicy[] = [];
const render = () =>
(renderResult = testRenderer.render(
- {
testRenderer = createFleetTestRendererMock();
});
- test('should not select agent policy by default if multiple exists', async () => {
+ test('should select first agent policy by default if multiple exists', async () => {
agentPolicies = [
{ id: 'policy-1', name: 'Policy 1' } as AgentPolicy,
{ id: 'policy-2', name: 'Policy 2' } as AgentPolicy,
@@ -45,7 +46,7 @@ describe('step select agent policy', () => {
await act(async () => {
const select = renderResult.container.querySelector('[data-test-subj="agentPolicyDropdown"]');
- expect((select as any)?.value).toEqual('');
+ expect((select as any)?.value).toEqual('policy-1');
expect(renderResult.getAllByRole('option').length).toBe(2);
});
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_selection.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_selection.tsx
index 3227308d93b9c..63737adb5caea 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_selection.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_selection.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import React, { useState, useEffect } from 'react';
+import React, { useEffect } from 'react';
import styled from 'styled-components';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
@@ -34,10 +34,10 @@ const AgentPolicyFormRow = styled(EuiFormRow)`
type Props = {
agentPolicies: AgentPolicy[];
- onAgentPolicyChange: (key?: string, policy?: AgentPolicy) => void;
+ selectedPolicy?: AgentPolicy;
+ setSelectedPolicyId: (agentPolicyId?: string) => void;
excludeFleetServer?: boolean;
onClickCreatePolicy: () => void;
- selectedAgentPolicy?: string;
isFleetServerPolicy?: boolean;
} & (
| {
@@ -63,44 +63,33 @@ const resolveAgentId = (
return selectedAgentPolicyId;
};
-export const EnrollmentStepAgentPolicy: React.FC = (props) => {
+export const AgentPolicySelection: React.FC = (props) => {
const {
agentPolicies,
- onAgentPolicyChange,
+ selectedPolicy,
+ setSelectedPolicyId,
excludeFleetServer,
onClickCreatePolicy,
- selectedAgentPolicy,
isFleetServerPolicy,
} = props;
- const [selectedAgentPolicyId, setSelectedAgentPolicyId] = useState(
- () => resolveAgentId(agentPolicies, undefined) // no agent id selected yet
- );
-
const hasFleetAllPrivileges = useAuthz().fleet.all;
- useEffect(
- function triggerOnAgentPolicyChangeEffect() {
- if (onAgentPolicyChange) {
- onAgentPolicyChange(selectedAgentPolicyId);
- }
- },
- [selectedAgentPolicyId, onAgentPolicyChange]
- );
-
useEffect(
function useDefaultAgentPolicyEffect() {
- const resolvedId = resolveAgentId(agentPolicies, selectedAgentPolicyId);
- if (resolvedId !== selectedAgentPolicyId) {
- setSelectedAgentPolicyId(resolvedId);
+ const resolvedId = resolveAgentId(agentPolicies, selectedPolicy?.id);
+ // find AgentPolicy
+ if (resolvedId !== selectedPolicy?.id) {
+ setSelectedPolicyId(resolvedId);
}
},
- [agentPolicies, selectedAgentPolicyId]
+ [agentPolicies, setSelectedPolicyId, selectedPolicy]
);
- useEffect(() => {
- if (selectedAgentPolicy) setSelectedAgentPolicyId(selectedAgentPolicy);
- }, [selectedAgentPolicy]);
+ const onChangeCallback = (event: React.ChangeEvent) => {
+ const { value } = event.target;
+ setSelectedPolicyId(value);
+ };
return (
<>
@@ -154,24 +143,24 @@ export const EnrollmentStepAgentPolicy: React.FC = (props) => {
value: agentPolicy.id,
text: agentPolicy.name,
}))}
- value={selectedAgentPolicyId}
- onChange={(e) => setSelectedAgentPolicyId(e.target.value)}
+ value={selectedPolicy?.id}
+ onChange={onChangeCallback}
aria-label={i18n.translate(
'xpack.fleet.enrollmentStepAgentPolicy.policySelectAriaLabel',
{
defaultMessage: 'Agent policy',
}
)}
- hasNoInitialSelection={!selectedAgentPolicyId}
+ hasNoInitialSelection={!selectedPolicy?.id}
data-test-subj="agentPolicyDropdown"
- isInvalid={!selectedAgentPolicyId}
+ isInvalid={!selectedPolicy?.id}
/>
- {selectedAgentPolicyId && !isFleetServerPolicy && (
+ {selectedPolicy?.id && !isFleetServerPolicy && (
<>
>
@@ -183,7 +172,7 @@ export const EnrollmentStepAgentPolicy: React.FC = (props) => {
selectedApiKeyId={props.selectedApiKeyId}
onKeyChange={props.onKeyChange}
initialAuthenticationSettingsOpen={!props.selectedApiKeyId}
- agentPolicyId={selectedAgentPolicyId}
+ agentPolicyId={selectedPolicy?.id}
/>
>
)}
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_agent_enrollment.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_agent_enrollment.tsx
index dd39f8700e4fb..63292713daa93 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_agent_enrollment.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_agent_enrollment.tsx
@@ -5,29 +5,99 @@
* 2.0.
*/
-import React from 'react';
-import { EuiCallOut, EuiButton } from '@elastic/eui';
+import React, { useEffect, useRef, useState } from 'react';
+import { EuiCallOut, EuiButton, EuiText, EuiLink } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n-react';
import { i18n } from '@kbn/i18n';
-import { useGetAgentStatus } from '../../hooks';
+import { sendGetAgents, useLink, useStartServices } from '../../hooks';
import { AGENTS_PREFIX } from '../../constants';
interface Props {
- policyId: string;
- onClickViewAgents: () => void;
+ policyId?: string;
+ troubleshootLink: string;
+ onClickViewAgents?: () => void;
+ agentCount: number;
}
+const POLLING_INTERVAL_MS = 5 * 1000; // 5 sec
+
+/**
+ * Hook for finding agents enrolled since component was rendered. Should be
+ * used by parent component to power rendering
+ * @param policyId
+ * @returns agentIds
+ */
+export const usePollingAgentCount = (policyId: string) => {
+ const [agentIds, setAgentIds] = useState([]);
+
+ const timeout = useRef(undefined);
+
+ useEffect(() => {
+ let isAborted = false;
+
+ const poll = () => {
+ timeout.current = window.setTimeout(async () => {
+ const request = await sendGetAgents({
+ kuery: `${AGENTS_PREFIX}.policy_id:"${policyId}" and ${AGENTS_PREFIX}.enrolled_at >= now-10m`,
+ showInactive: false,
+ });
+
+ const newAgentIds = request.data?.items.map((i) => i.id) ?? agentIds;
+ if (newAgentIds.some((id) => !agentIds.includes(id))) {
+ setAgentIds(newAgentIds);
+ }
+ if (!isAborted) {
+ poll();
+ }
+ }, POLLING_INTERVAL_MS);
+ };
+
+ poll();
+
+ if (isAborted || agentIds.length > 0) clearTimeout(timeout.current);
+
+ return () => {
+ isAborted = true;
+ };
+ }, [agentIds, policyId]);
+ return agentIds;
+};
+
export const ConfirmAgentEnrollment: React.FunctionComponent = ({
policyId,
+ troubleshootLink,
onClickViewAgents,
+ agentCount,
}) => {
- // Check the agents enrolled in the last 10 minutes
- const enrolledAt = 'now-10m';
- const kuery = `${AGENTS_PREFIX}.enrolled_at >= "${enrolledAt}"`;
- const agentStatusRequest = useGetAgentStatus({ kuery, policyId });
- const agentsCount = agentStatusRequest.data?.results?.total;
-
- if (!agentsCount) {
- return null;
+ const { getHref } = useLink();
+ const { application } = useStartServices();
+
+ const onButtonClick = () => {
+ if (onClickViewAgents) onClickViewAgents();
+ const href = getHref('agent_list');
+ application.navigateToUrl(href);
+ };
+
+ if (!policyId || agentCount === 0) {
+ return (
+
+
+
+
+ ),
+ }}
+ />
+
+ );
}
return (
@@ -35,16 +105,16 @@ export const ConfirmAgentEnrollment: React.FunctionComponent = ({
data-test-subj="ConfirmAgentEnrollmentCallOut"
title={i18n.translate('xpack.fleet.agentEnrollment.confirmation.title', {
defaultMessage:
- '{agentsCount} {agentsCount, plural, one {agent has} other {agents have}} been enrolled.',
+ '{agentCount} {agentCount, plural, one {agent has} other {agents have}} been enrolled.',
values: {
- agentsCount,
+ agentCount,
},
})}
color="success"
iconType="check"
>
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_incoming_data.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_incoming_data.tsx
index 85817fa9850a0..b74129e443e45 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_incoming_data.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_incoming_data.tsx
@@ -9,67 +9,74 @@ import React from 'react';
import { EuiCallOut, EuiText, EuiSpacer, EuiButton } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import type { InstalledIntegrationPolicy } from '../../hooks';
-import { useGetAgentIncomingData } from '../../hooks';
+import type { InstalledIntegrationPolicy } from './use_get_agent_incoming_data';
+import { useGetAgentIncomingData, usePollingIncomingData } from './use_get_agent_incoming_data';
+
interface Props {
- agentsIds: string[];
+ agentIds: string[];
installedPolicy?: InstalledIntegrationPolicy;
+ agentDataConfirmed: boolean;
+ setAgentDataConfirmed: (v: boolean) => void;
}
export const ConfirmIncomingData: React.FunctionComponent = ({
- agentsIds,
+ agentIds,
installedPolicy,
+ agentDataConfirmed,
+ setAgentDataConfirmed,
}) => {
- const { enrolledAgents, numAgentsWithData, isLoading, linkButton } = useGetAgentIncomingData(
- agentsIds,
+ const { incomingData, isLoading } = usePollingIncomingData(agentIds);
+
+ const { enrolledAgents, numAgentsWithData, linkButton, message } = useGetAgentIncomingData(
+ incomingData,
installedPolicy
);
+ if (!isLoading && enrolledAgents > 0 && numAgentsWithData > 0) {
+ setAgentDataConfirmed(true);
+ }
+ if (!agentDataConfirmed) {
+ return (
+
+ {i18n.translate('xpack.fleet.confirmIncomingData.loading', {
+ defaultMessage:
+ 'It may take a few minutes for data to arrive in Elasticsearch. If the system is not generating data, it may help to generate some to ensure data is being collected correctly. If you’re having trouble, see our troubleshooting guide. You may close this dialog and check later by viewing our integration assets.',
+ })}
+
+ );
+ }
+
return (
<>
- {isLoading ? (
-
- {i18n.translate('xpack.fleet.confirmIncomingData.loading', {
- defaultMessage:
- 'It may take a few minutes for data to arrive in Elasticsearch. If the system is not generating data, it may help to generate some to ensure data is being collected correctly. If you’re having trouble, see our troubleshooting guide. You may close this dialog and check later by viewing our integration assets.',
- })}
-
- ) : (
+
+ {installedPolicy && (
<>
-
-
- {i18n.translate('xpack.fleet.confirmIncomingData.subtitle', {
- defaultMessage: 'Your agent is enrolled successfully and your data is received.',
- })}
-
+ {message}
+
+
+ {linkButton.text}
+
>
)}
-
-
- {installedPolicy && (
-
- {linkButton.text}
-
- )}
>
);
};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/default_missing_requirements.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/default_missing_requirements.tsx
new file mode 100644
index 0000000000000..d7ae0a441d66f
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/default_missing_requirements.tsx
@@ -0,0 +1,35 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { EuiLink } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n-react';
+
+import { useLink } from '../../hooks';
+
+export const DefaultMissingRequirements = () => {
+ const { getHref } = useLink();
+
+ return (
+ <>
+
+
+
+ ),
+ }}
+ />
+ >
+ );
+};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/hooks.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/hooks.tsx
index d7b48b5a961c2..159de12ff578c 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/hooks.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/hooks.tsx
@@ -9,8 +9,11 @@ import { i18n } from '@kbn/i18n';
import type { PackagePolicy, AgentPolicy } from '../../types';
import { sendGetOneAgentPolicy, useStartServices } from '../../hooks';
+
import { FLEET_KUBERNETES_PACKAGE } from '../../../common';
+import type { K8sMode } from './types';
+
export function useAgentPolicyWithPackagePolicies(policyId?: string) {
const [agentPolicyWithPackagePolicies, setAgentPolicy] = useState(null);
const core = useStartServices();
@@ -41,9 +44,7 @@ export function useAgentPolicyWithPackagePolicies(policyId?: string) {
}
export function useIsK8sPolicy(agentPolicy?: AgentPolicy) {
- const [isK8s, setIsK8s] = useState<'IS_LOADING' | 'IS_KUBERNETES' | 'IS_NOT_KUBERNETES'>(
- 'IS_LOADING'
- );
+ const [isK8s, setIsK8s] = useState('IS_LOADING');
useEffect(() => {
async function checkifK8s() {
if (!agentPolicy) {
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx
index ed4cc15aec196..0adcfb26aa9c2 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx
@@ -24,43 +24,42 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { useGetSettings, useFleetStatus, useAgentEnrollmentFlyoutData } from '../../hooks';
import { FLEET_SERVER_PACKAGE } from '../../constants';
-import type { PackagePolicy } from '../../types';
+import type { PackagePolicy, AgentPolicy } from '../../types';
import { Loading } from '..';
-import { ManagedInstructions } from './managed_instructions';
-import { StandaloneInstructions } from './standalone_instructions';
+import { Instructions } from './instructions';
import { MissingFleetServerHostCallout } from './missing_fleet_server_host_callout';
-import type { BaseProps } from './types';
-import { useIsK8sPolicy, useAgentPolicyWithPackagePolicies } from './hooks';
-
-type FlyoutMode = 'managed' | 'standalone';
+import type { FlyOutProps, SelectionType, FlyoutMode } from './types';
-export interface Props extends BaseProps {
- onClose: () => void;
- defaultMode?: FlyoutMode;
-}
+import { useIsK8sPolicy, useAgentPolicyWithPackagePolicies } from './hooks';
export * from './agent_policy_selection';
export * from './agent_policy_select_create';
-export * from './managed_instructions';
-export * from './standalone_instructions';
+export * from './instructions';
export * from './steps';
-export const AgentEnrollmentFlyout: React.FunctionComponent = ({
+export const AgentEnrollmentFlyout: React.FunctionComponent = ({
onClose,
agentPolicy,
- viewDataStep,
defaultMode = 'managed',
+ isIntegrationFlow,
+ installedPackagePolicy,
}) => {
- const [mode, setMode] = useState(defaultMode);
+ const findPolicyById = (policies: AgentPolicy[], id: string | undefined) => {
+ if (!id) return undefined;
+ return policies.find((p) => p.id === id);
+ };
const settings = useGetSettings();
+ const fleetStatus = useFleetStatus();
const fleetServerHosts = settings.data?.item?.fleet_server_hosts || [];
- const fleetStatus = useFleetStatus();
- const [policyId, setSelectedPolicyId] = useState(agentPolicy?.id);
+ const [selectedPolicyId, setSelectedPolicyId] = useState(agentPolicy?.id);
const [isFleetServerPolicySelected, setIsFleetServerPolicySelected] = useState(false);
+ const [selectedApiKeyId, setSelectedAPIKeyId] = useState();
+ const [mode, setMode] = useState(defaultMode);
+ const [selectionType, setSelectionType] = useState('tabs');
const {
agentPolicies,
@@ -68,11 +67,19 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({
isLoadingAgentPolicies,
refreshAgentPolicies,
} = useAgentEnrollmentFlyoutData();
- const { agentPolicyWithPackagePolicies } = useAgentPolicyWithPackagePolicies(policyId);
+
+ const { agentPolicyWithPackagePolicies } = useAgentPolicyWithPackagePolicies(selectedPolicyId);
+
+ const selectedPolicy = agentPolicyWithPackagePolicies
+ ? agentPolicyWithPackagePolicies
+ : findPolicyById(agentPolicies, selectedPolicyId);
+
+ const hasNoFleetServerHost = fleetStatus.isReady && fleetServerHosts.length === 0;
+
useEffect(() => {
- if (agentPolicyWithPackagePolicies && setIsFleetServerPolicySelected) {
+ if (selectedPolicy) {
if (
- (agentPolicyWithPackagePolicies.package_policies as PackagePolicy[]).some(
+ (selectedPolicy.package_policies as PackagePolicy[]).some(
(packagePolicy) => packagePolicy.package?.name === FLEET_SERVER_PACKAGE
)
) {
@@ -81,11 +88,9 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({
setIsFleetServerPolicySelected(false);
}
}
- }, [agentPolicyWithPackagePolicies]);
+ }, [selectedPolicy, isFleetServerPolicySelected]);
- const { isK8s } = useIsK8sPolicy(
- agentPolicyWithPackagePolicies ? agentPolicyWithPackagePolicies : undefined
- );
+ const { isK8s } = useIsK8sPolicy(selectedPolicy ? selectedPolicy : undefined);
const isLoadingInitialRequest = settings.isLoading && settings.isInitialRequest;
@@ -107,61 +112,63 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({
defaultMessage="Add Elastic Agents to your hosts to collect data and send it to the Elastic Stack."
/>
-
-
- setMode('managed')}
- >
-
-
- setMode('standalone')}
- >
-
-
-
+ {selectionType === 'tabs' ? (
+ <>
+
+
+ setMode('managed')}
+ >
+
+
+ setMode('standalone')}
+ >
+
+
+
+ >
+ ) : null}
-
) : undefined
}
>
{isLoadingInitialAgentPolicies ? (
-
- ) : mode === 'managed' ? (
-
+ ) : (
+
- ) : (
-
)}
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/installation_message.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/installation_message.tsx
new file mode 100644
index 0000000000000..6bb178921c2a9
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/installation_message.tsx
@@ -0,0 +1,59 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+import React, { useMemo } from 'react';
+import { EuiText, EuiLink } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n-react';
+
+import semverMajor from 'semver/functions/major';
+import semverMinor from 'semver/functions/minor';
+import semverPatch from 'semver/functions/patch';
+
+import { useKibanaVersion } from '../../hooks';
+
+export const InstallationMessage: React.FunctionComponent = () => {
+ const kibanaVersion = useKibanaVersion();
+ const kibanaVersionURLString = useMemo(
+ () =>
+ `${semverMajor(kibanaVersion)}-${semverMinor(kibanaVersion)}-${semverPatch(kibanaVersion)}`,
+ [kibanaVersion]
+ );
+
+ return (
+
+
+
+
+ ),
+ installationLink: (
+
+
+
+ ),
+ }}
+ />
+
+ );
+};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/instructions.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/instructions.tsx
new file mode 100644
index 0000000000000..32ac217c353e8
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/instructions.tsx
@@ -0,0 +1,126 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { useMemo } from 'react';
+import { EuiText, EuiSpacer } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n-react';
+
+import { useFleetStatus, useGetAgents } from '../../hooks';
+
+import { FleetServerRequirementPage } from '../../applications/fleet/sections/agents/agent_requirements_page';
+
+import { policyHasFleetServer } from '../../applications/fleet/sections/agents/services/has_fleet_server';
+
+import { FLEET_SERVER_PACKAGE } from '../../constants';
+
+import { useFleetServerUnhealthy } from '../../applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy';
+
+import { Loading } from '..';
+
+import type { InstructionProps } from './types';
+
+import { ManagedSteps, StandaloneSteps, FleetServerSteps } from './steps';
+import { DefaultMissingRequirements } from './default_missing_requirements';
+
+export const Instructions = (props: InstructionProps) => {
+ const {
+ agentPolicies,
+ isFleetServerPolicySelected,
+ settings,
+ isLoadingAgentPolicies,
+ setSelectionType,
+ mode,
+ isIntegrationFlow,
+ } = props;
+ const fleetStatus = useFleetStatus();
+ const { isUnhealthy: isFleetServerUnhealthy } = useFleetServerUnhealthy();
+
+ const { data: agents, isLoading: isLoadingAgents } = useGetAgents({
+ page: 1,
+ perPage: 1000,
+ showInactive: false,
+ });
+
+ const fleetServers = useMemo(() => {
+ const fleetServerAgentPolicies: string[] = agentPolicies
+ .filter((pol) => policyHasFleetServer(pol))
+ .map((pol) => pol.id);
+ return (agents?.items ?? []).filter((agent) =>
+ fleetServerAgentPolicies.includes(agent.policy_id ?? '')
+ );
+ }, [agents, agentPolicies]);
+
+ const fleetServerHosts = useMemo(() => {
+ return settings?.fleet_server_hosts || [];
+ }, [settings]);
+
+ const hasNoFleetServerHost = fleetStatus.isReady && fleetServerHosts.length === 0;
+
+ const showAgentEnrollment =
+ fleetStatus.isReady &&
+ !isFleetServerUnhealthy &&
+ fleetServers.length > 0 &&
+ fleetServerHosts.length > 0;
+
+ const showFleetServerEnrollment =
+ fleetServers.length === 0 ||
+ isFleetServerUnhealthy ||
+ (fleetStatus.missingRequirements ?? []).some((r) => r === FLEET_SERVER_PACKAGE);
+
+ if (!isIntegrationFlow && showAgentEnrollment) {
+ setSelectionType('radio');
+ } else {
+ setSelectionType('tabs');
+ }
+
+ if (isLoadingAgents || isLoadingAgentPolicies) return ;
+
+ if (hasNoFleetServerHost) {
+ return null;
+ }
+
+ if (mode === 'managed') {
+ if (showFleetServerEnrollment) {
+ return ;
+ } else if (showAgentEnrollment) {
+ return (
+ <>
+
+
+
+
+ {isFleetServerPolicySelected ? (
+
+ ) : (
+
+ )}
+ >
+ );
+ }
+ return ;
+ } else {
+ return ;
+ }
+};
+
+const StandaloneInstructions = (props: InstructionProps) => {
+ return (
+ <>
+
+
+
+
+
+ >
+ );
+};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/managed_instructions.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/managed_instructions.tsx
deleted file mode 100644
index 1e2141ea3827f..0000000000000
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/managed_instructions.tsx
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import React, { useState, useMemo } from 'react';
-import { EuiSteps, EuiLink, EuiText, EuiSpacer } from '@elastic/eui';
-import type { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps';
-import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n-react';
-
-import { useGetOneEnrollmentAPIKey, useLink, useFleetStatus, useGetAgents } from '../../hooks';
-
-import { ManualInstructions } from '../../components/enrollment_instructions';
-import {
- deploymentModeStep,
- ServiceTokenStep,
- FleetServerCommandStep,
- useFleetServerInstructions,
- addFleetServerHostStep,
-} from '../../applications/fleet/sections/agents/agent_requirements_page/components';
-import { FleetServerRequirementPage } from '../../applications/fleet/sections/agents/agent_requirements_page';
-
-import { policyHasFleetServer } from '../../applications/fleet/sections/agents/services/has_fleet_server';
-
-import { FLEET_SERVER_PACKAGE } from '../../constants';
-
-import { DownloadStep, AgentPolicySelectionStep, AgentEnrollmentKeySelectionStep } from './steps';
-import type { InstructionProps } from './types';
-
-const DefaultMissingRequirements = () => {
- const { getHref } = useLink();
-
- return (
- <>
-
-
-
- ),
- }}
- />
- >
- );
-};
-
-const FleetServerMissingRequirements = () => {
- return ;
-};
-
-export const ManagedInstructions = React.memo(
- ({
- agentPolicy,
- agentPolicies,
- viewDataStep,
- setSelectedPolicyId,
- policyId,
- isFleetServerPolicySelected,
- isK8s,
- settings,
- refreshAgentPolicies,
- isLoadingAgentPolicies,
- }) => {
- const fleetStatus = useFleetStatus();
- const [selectedApiKeyId, setSelectedAPIKeyId] = useState();
- const apiKey = useGetOneEnrollmentAPIKey(selectedApiKeyId);
- const fleetServerInstructions = useFleetServerInstructions(apiKey?.data?.item?.policy_id);
-
- const { data: agents, isLoading: isLoadingAgents } = useGetAgents({
- page: 1,
- perPage: 1000,
- showInactive: false,
- });
-
- const fleetServers = useMemo(() => {
- const fleetServerAgentPolicies: string[] = agentPolicies
- .filter((pol) => policyHasFleetServer(pol))
- .map((pol) => pol.id);
- return (agents?.items ?? []).filter((agent) =>
- fleetServerAgentPolicies.includes(agent.policy_id ?? '')
- );
- }, [agents, agentPolicies]);
-
- const fleetServerSteps = useMemo(() => {
- const {
- serviceToken,
- getServiceToken,
- isLoadingServiceToken,
- installCommand,
- platform,
- setPlatform,
- deploymentMode,
- setDeploymentMode,
- addFleetServerHost,
- } = fleetServerInstructions;
-
- return [
- deploymentModeStep({ deploymentMode, setDeploymentMode }),
- addFleetServerHostStep({ addFleetServerHost }),
- ServiceTokenStep({ serviceToken, getServiceToken, isLoadingServiceToken }),
- FleetServerCommandStep({ serviceToken, installCommand, platform, setPlatform }),
- ];
- }, [fleetServerInstructions]);
-
- const enrolToken = apiKey.data ? apiKey.data.item.api_key : '';
-
- const steps = useMemo(() => {
- const fleetServerHosts = settings?.fleet_server_hosts || [];
- const baseSteps: EuiContainedStepProps[] = [
- !agentPolicy
- ? AgentPolicySelectionStep({
- agentPolicies,
- selectedApiKeyId,
- setSelectedAPIKeyId,
- setSelectedPolicyId,
- refreshAgentPolicies,
- })
- : AgentEnrollmentKeySelectionStep({ agentPolicy, selectedApiKeyId, setSelectedAPIKeyId }),
- DownloadStep(isFleetServerPolicySelected || false, isK8s || '', enrolToken || ''),
- ];
- if (isFleetServerPolicySelected) {
- baseSteps.push(...fleetServerSteps);
- } else {
- baseSteps.push({
- title: i18n.translate('xpack.fleet.agentEnrollment.stepEnrollAndRunAgentTitle', {
- defaultMessage: 'Enroll and start the Elastic Agent',
- }),
- children: selectedApiKeyId && apiKey.data && (
-
- ),
- });
- }
-
- if (viewDataStep) {
- baseSteps.push({ 'data-test-subj': 'view-data-step', ...viewDataStep });
- }
-
- return baseSteps;
- }, [
- agentPolicy,
- selectedApiKeyId,
- setSelectedPolicyId,
- setSelectedAPIKeyId,
- agentPolicies,
- refreshAgentPolicies,
- apiKey.data,
- fleetServerSteps,
- isFleetServerPolicySelected,
- settings?.fleet_server_hosts,
- viewDataStep,
- enrolToken,
- isK8s,
- policyId,
- ]);
-
- if (fleetStatus.isReady && settings?.fleet_server_hosts.length === 0) {
- return null;
- }
-
- if (
- fleetStatus.isReady &&
- (isLoadingAgents || isLoadingAgentPolicies || fleetServers.length > 0)
- ) {
- return (
- <>
-
-
-
-
-
- >
- );
- }
-
- const showFleetMissingRequirements =
- fleetServers.length === 0 ||
- (fleetStatus.missingRequirements ?? []).some((r) => r === FLEET_SERVER_PACKAGE);
-
- return (
- <>
- {showFleetMissingRequirements ? (
-
- ) : (
-
- )}
- >
- );
- }
-);
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/standalone_instructions.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/standalone_instructions.tsx
deleted file mode 100644
index 4df0431252135..0000000000000
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/standalone_instructions.tsx
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import React, { useState, useEffect } from 'react';
-import {
- EuiSteps,
- EuiText,
- EuiSpacer,
- EuiButton,
- EuiCode,
- EuiFlexItem,
- EuiFlexGroup,
- EuiCodeBlock,
- EuiCopy,
- EuiLink,
-} from '@elastic/eui';
-import type { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps';
-import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n-react';
-import { safeDump } from 'js-yaml';
-
-import {
- useStartServices,
- useLink,
- sendGetOneAgentPolicyFull,
- useKibanaVersion,
-} from '../../hooks';
-import { fullAgentPolicyToYaml, agentPolicyRouteService } from '../../services';
-
-import { PlatformSelector } from '../enrollment_instructions/manual/platform_selector';
-
-import { DownloadStep, AgentPolicySelectionStep } from './steps';
-import type { InstructionProps } from './types';
-import { useIsK8sPolicy, useAgentPolicyWithPackagePolicies } from './hooks';
-
-export const StandaloneInstructions = React.memo(
- ({ agentPolicy, agentPolicies, refreshAgentPolicies }) => {
- const { getHref } = useLink();
- const core = useStartServices();
- const { notifications } = core;
-
- const [selectedPolicyId, setSelectedPolicyId] = useState(agentPolicy?.id);
- const [fullAgentPolicy, setFullAgentPolicy] = useState();
- const [yaml, setYaml] = useState('');
- const kibanaVersion = useKibanaVersion();
-
- const { agentPolicyWithPackagePolicies } = useAgentPolicyWithPackagePolicies(selectedPolicyId);
- const { isK8s } = useIsK8sPolicy(
- agentPolicyWithPackagePolicies ? agentPolicyWithPackagePolicies : undefined
- );
-
- const KUBERNETES_RUN_INSTRUCTIONS = 'kubectl apply -f elastic-agent-standalone-kubernetes.yaml';
-
- const STANDALONE_RUN_INSTRUCTIONS_LINUX = `curl -L -O https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-${kibanaVersion}-linux-x86_64.tar.gz
-tar xzvf elastic-agent-${kibanaVersion}-linux-x86_64.tar.gz
-sudo ./elastic-agent install`;
-
- const STANDALONE_RUN_INSTRUCTIONS_MAC = `curl -L -O https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-${kibanaVersion}-darwin-x86_64.tar.gz
-tar xzvf elastic-agent-${kibanaVersion}-darwin-x86_64.tar.gz
-sudo ./elastic-agent install`;
-
- const STANDALONE_RUN_INSTRUCTIONS_WINDOWS = `wget https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-${kibanaVersion}-windows-x86_64.zip -OutFile elastic-agent-${kibanaVersion}-windows-x86_64.zip
-Expand-Archive .\\elastic-agent-${kibanaVersion}-windows-x86_64.zip
-.\\elastic-agent.exe install`;
-
- const linuxDebCommand = `curl -L -O https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-${kibanaVersion}-amd64.deb
-sudo dpkg -i elastic-agent-${kibanaVersion}-amd64.deb \nsudo systemctl enable elastic-agent \nsudo systemctl start elastic-agent`;
-
- const linuxRpmCommand = `curl -L -O https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-${kibanaVersion}-x86_64.rpm
-sudo rpm -vi elastic-agent-${kibanaVersion}-x86_64.rpm \nsudo systemctl enable elastic-agent \nsudo systemctl start elastic-agent`;
-
- const linuxCommand =
- isK8s === 'IS_KUBERNETES' ? KUBERNETES_RUN_INSTRUCTIONS : STANDALONE_RUN_INSTRUCTIONS_LINUX;
- const macCommand =
- isK8s === 'IS_KUBERNETES' ? KUBERNETES_RUN_INSTRUCTIONS : STANDALONE_RUN_INSTRUCTIONS_MAC;
- const windowsCommand =
- isK8s === 'IS_KUBERNETES' ? KUBERNETES_RUN_INSTRUCTIONS : STANDALONE_RUN_INSTRUCTIONS_WINDOWS;
-
- const { docLinks } = useStartServices();
-
- useEffect(() => {
- async function fetchFullPolicy() {
- try {
- if (!selectedPolicyId) {
- return;
- }
- let query = { standalone: true, kubernetes: false };
- if (isK8s === 'IS_KUBERNETES') {
- query = { standalone: true, kubernetes: true };
- }
- const res = await sendGetOneAgentPolicyFull(selectedPolicyId, query);
- if (res.error) {
- throw res.error;
- }
-
- if (!res.data) {
- throw new Error('No data while fetching full agent policy');
- }
- setFullAgentPolicy(res.data.item);
- } catch (error) {
- notifications.toasts.addError(error, {
- title: 'Error',
- });
- }
- }
- if (isK8s !== 'IS_LOADING') {
- fetchFullPolicy();
- }
- }, [selectedPolicyId, notifications.toasts, isK8s, core.http.basePath]);
-
- useEffect(() => {
- if (isK8s === 'IS_KUBERNETES') {
- if (typeof fullAgentPolicy === 'object') {
- return;
- }
- setYaml(fullAgentPolicy);
- } else {
- if (typeof fullAgentPolicy === 'string') {
- return;
- }
- setYaml(fullAgentPolicyToYaml(fullAgentPolicy, safeDump));
- }
- }, [fullAgentPolicy, isK8s]);
-
- const policyMsg =
- isK8s === 'IS_KUBERNETES' ? (
- ES_USERNAME,
- ESPasswordVariable: ES_PASSWORD,
- }}
- />
- ) : (
- elastic-agent.yml,
- ESUsernameVariable: ES_USERNAME,
- ESPasswordVariable: ES_PASSWORD,
- outputSection: outputs,
- }}
- />
- );
-
- let downloadLink = '';
- if (selectedPolicyId) {
- downloadLink =
- isK8s === 'IS_KUBERNETES'
- ? core.http.basePath.prepend(
- `${agentPolicyRouteService.getInfoFullDownloadPath(
- selectedPolicyId
- )}?kubernetes=true&standalone=true`
- )
- : core.http.basePath.prepend(
- `${agentPolicyRouteService.getInfoFullDownloadPath(selectedPolicyId)}?standalone=true`
- );
- }
-
- const downloadMsg =
- isK8s === 'IS_KUBERNETES' ? (
-
- ) : (
-
- );
-
- const steps = [
- !agentPolicy
- ? AgentPolicySelectionStep({
- agentPolicies,
- setSelectedPolicyId,
- excludeFleetServer: true,
- refreshAgentPolicies,
- })
- : undefined,
- DownloadStep(false),
- {
- title: i18n.translate('xpack.fleet.agentEnrollment.stepConfigureAgentTitle', {
- defaultMessage: 'Configure the agent',
- }),
- children: (
- <>
-
- <>{policyMsg}>
-
-
-
-
- {(copy) => (
-
-
-
- )}
-
-
-
-
- <>{downloadMsg}>
-
-
-
-
-
- {yaml}
-
-
- >
- ),
- },
- {
- title: i18n.translate('xpack.fleet.agentEnrollment.stepRunAgentTitle', {
- defaultMessage: 'Start the agent',
- }),
- children: (
-
- ),
- },
- {
- title: i18n.translate('xpack.fleet.agentEnrollment.stepCheckForDataTitle', {
- defaultMessage: 'Check for data',
- }),
- children: (
- <>
-
-
-
-
- ),
- }}
- />
-
- >
- ),
- },
- ].filter(Boolean) as EuiContainedStepProps[];
-
- return (
- <>
-
-
-
-
-
- >
- );
- }
-);
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_enrollment_confirmation_step.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_enrollment_confirmation_step.tsx
new file mode 100644
index 0000000000000..743bf1a7fa578
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_enrollment_confirmation_step.tsx
@@ -0,0 +1,41 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { i18n } from '@kbn/i18n';
+
+import type { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps';
+
+import { ConfirmAgentEnrollment } from '../confirm_agent_enrollment';
+
+export const AgentEnrollmentConfirmationStep = ({
+ selectedPolicyId,
+ troubleshootLink,
+ onClickViewAgents,
+ agentCount,
+}: {
+ selectedPolicyId?: string;
+ troubleshootLink: string;
+ onClickViewAgents: () => void;
+ agentCount: number;
+}): EuiContainedStepProps => {
+ return {
+ title: i18n.translate('xpack.fleet.agentEnrollment.stepAgentEnrollmentConfirmation', {
+ defaultMessage: 'Confirm agent Enrollment',
+ }),
+ children: (
+
+ ),
+ status: !agentCount ? 'incomplete' : 'complete',
+ };
+};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_enrollment_key_selection_step.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_enrollment_key_selection_step.tsx
new file mode 100644
index 0000000000000..bc67e834f1d22
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_enrollment_key_selection_step.tsx
@@ -0,0 +1,53 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { EuiText, EuiSpacer } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n-react';
+import { i18n } from '@kbn/i18n';
+
+import type { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps';
+
+import type { AgentPolicy } from '../../../types';
+
+import { AdvancedAgentAuthenticationSettings } from '../advanced_agent_authentication_settings';
+
+export const AgentEnrollmentKeySelectionStep = ({
+ selectedPolicy,
+ selectedApiKeyId,
+ setSelectedAPIKeyId,
+}: {
+ selectedPolicy?: AgentPolicy;
+ selectedApiKeyId?: string;
+ setSelectedAPIKeyId: (key?: string) => void;
+}): EuiContainedStepProps => {
+ return {
+ title: i18n.translate('xpack.fleet.agentEnrollment.stepConfigurePolicyAuthenticationTitle', {
+ defaultMessage: 'Select enrollment token',
+ }),
+ children: (
+ <>
+
+ {selectedPolicy?.name},
+ }}
+ />
+
+
+
+ >
+ ),
+ };
+};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_policy_selection_step.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_policy_selection_step.tsx
new file mode 100644
index 0000000000000..c26bfd3f0e2b8
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_policy_selection_step.tsx
@@ -0,0 +1,54 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { i18n } from '@kbn/i18n';
+
+import type { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps';
+
+import type { AgentPolicy } from '../../../types';
+
+import { SelectCreateAgentPolicy } from '../agent_policy_select_create';
+
+export const AgentPolicySelectionStep = ({
+ agentPolicies,
+ selectedPolicy,
+ setSelectedPolicyId,
+ selectedApiKeyId,
+ setSelectedAPIKeyId,
+ excludeFleetServer,
+ refreshAgentPolicies,
+}: {
+ agentPolicies: AgentPolicy[];
+ selectedPolicy?: AgentPolicy;
+ setSelectedPolicyId: (agentPolicyId?: string) => void;
+ selectedApiKeyId?: string;
+ setSelectedAPIKeyId?: (key?: string) => void;
+ excludeFleetServer?: boolean;
+ refreshAgentPolicies: () => void;
+}): EuiContainedStepProps => {
+ return {
+ title: i18n.translate('xpack.fleet.agentEnrollment.stepChooseAgentPolicyTitle', {
+ defaultMessage: 'What type of host are you adding?',
+ }),
+ children: (
+ <>
+
+ >
+ ),
+ };
+};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/compute_steps.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/compute_steps.tsx
new file mode 100644
index 0000000000000..cae508299f259
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/compute_steps.tsx
@@ -0,0 +1,369 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { useState, useMemo, useEffect } from 'react';
+
+import { EuiSteps } from '@elastic/eui';
+import { safeDump } from 'js-yaml';
+
+import type { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps';
+
+import type { FullAgentPolicy } from '../../../../common/types/models/agent_policy';
+
+import { fullAgentPolicyToYaml, agentPolicyRouteService } from '../../../services';
+
+import { StandaloneInstructions } from '../../enrollment_instructions/standalone';
+
+import {
+ useGetOneEnrollmentAPIKey,
+ useStartServices,
+ useKibanaVersion,
+ sendGetOneAgentPolicyFull,
+} from '../../../hooks';
+
+import {
+ deploymentModeStep,
+ ServiceTokenStep,
+ FleetServerCommandStep,
+ useFleetServerInstructions,
+ addFleetServerHostStep,
+} from '../../../applications/fleet/sections/agents/agent_requirements_page/components';
+
+import type { InstructionProps } from '../types';
+import { usePollingAgentCount } from '../confirm_agent_enrollment';
+
+import {
+ InstallationModeSelectionStep,
+ AgentEnrollmentKeySelectionStep,
+ AgentPolicySelectionStep,
+ InstallStandaloneAgentStep,
+ ConfigureStandaloneAgentStep,
+ AgentEnrollmentConfirmationStep,
+ InstallManagedAgentStep,
+ IncomingDataConfirmationStep,
+} from '.';
+
+export const StandaloneSteps: React.FunctionComponent = ({
+ agentPolicy,
+ agentPolicies,
+ selectedPolicy,
+ setSelectedPolicyId,
+ refreshAgentPolicies,
+ mode,
+ setMode,
+ selectionType,
+ selectedApiKeyId,
+ setSelectedAPIKeyId,
+ isK8s,
+}) => {
+ const core = useStartServices();
+ const { notifications } = core;
+ const [fullAgentPolicy, setFullAgentPolicy] = useState();
+ const [yaml, setYaml] = useState('');
+ const kibanaVersion = useKibanaVersion();
+
+ let downloadLink = '';
+
+ if (selectedPolicy?.id) {
+ downloadLink =
+ isK8s === 'IS_KUBERNETES'
+ ? core.http.basePath.prepend(
+ `${agentPolicyRouteService.getInfoFullDownloadPath(
+ selectedPolicy?.id
+ )}?kubernetes=true&standalone=true`
+ )
+ : core.http.basePath.prepend(
+ `${agentPolicyRouteService.getInfoFullDownloadPath(selectedPolicy?.id)}?standalone=true`
+ );
+ }
+
+ useEffect(() => {
+ async function fetchFullPolicy() {
+ try {
+ if (!selectedPolicy?.id) {
+ return;
+ }
+ let query = { standalone: true, kubernetes: false };
+ if (isK8s === 'IS_KUBERNETES') {
+ query = { standalone: true, kubernetes: true };
+ }
+ const res = await sendGetOneAgentPolicyFull(selectedPolicy?.id, query);
+ if (res.error) {
+ throw res.error;
+ }
+
+ if (!res.data) {
+ throw new Error('No data while fetching full agent policy');
+ }
+ setFullAgentPolicy(res.data.item);
+ } catch (error) {
+ notifications.toasts.addError(error, {
+ title: 'Error',
+ });
+ }
+ }
+ if (isK8s !== 'IS_LOADING') {
+ fetchFullPolicy();
+ }
+ }, [selectedPolicy, notifications.toasts, isK8s, core.http.basePath]);
+
+ useEffect(() => {
+ if (!fullAgentPolicy) {
+ return;
+ }
+ if (isK8s === 'IS_KUBERNETES') {
+ if (typeof fullAgentPolicy === 'object') {
+ return;
+ }
+ setYaml(fullAgentPolicy);
+ } else {
+ if (typeof fullAgentPolicy === 'string') {
+ return;
+ }
+ setYaml(fullAgentPolicyToYaml(fullAgentPolicy, safeDump));
+ }
+ }, [fullAgentPolicy, isK8s]);
+
+ const instructionsSteps = useMemo(() => {
+ const standaloneInstallCommands = StandaloneInstructions(kibanaVersion, isK8s);
+
+ const steps: EuiContainedStepProps[] = !agentPolicy
+ ? [
+ AgentPolicySelectionStep({
+ selectedPolicy,
+ agentPolicies,
+ selectedApiKeyId,
+ setSelectedAPIKeyId,
+ setSelectedPolicyId,
+ refreshAgentPolicies,
+ }),
+ ]
+ : [];
+
+ if (selectionType === 'radio') {
+ steps.push(InstallationModeSelectionStep({ mode, setMode }));
+ }
+
+ steps.push(
+ ConfigureStandaloneAgentStep({
+ isK8s,
+ selectedPolicyId: selectedPolicy?.id,
+ yaml,
+ downloadLink,
+ })
+ );
+
+ steps.push(
+ InstallStandaloneAgentStep({
+ installCommand: standaloneInstallCommands,
+ isK8s,
+ selectedPolicyId: selectedPolicy?.id,
+ })
+ );
+
+ return steps;
+ }, [
+ kibanaVersion,
+ isK8s,
+ agentPolicy,
+ selectedPolicy,
+ agentPolicies,
+ selectedApiKeyId,
+ setSelectedAPIKeyId,
+ setSelectedPolicyId,
+ refreshAgentPolicies,
+ selectionType,
+ yaml,
+ downloadLink,
+ mode,
+ setMode,
+ ]);
+
+ return ;
+};
+
+export const ManagedSteps: React.FunctionComponent = ({
+ agentPolicy,
+ agentPolicies,
+ selectedPolicy,
+ setSelectedPolicyId,
+ selectedApiKeyId,
+ setSelectedAPIKeyId,
+ settings,
+ refreshAgentPolicies,
+ mode,
+ setMode,
+ selectionType,
+ onClickViewAgents,
+ isK8s,
+ installedPackagePolicy,
+}) => {
+ const core = useStartServices();
+ const { docLinks } = core;
+ const link = docLinks.links.fleet.troubleshooting;
+ const [agentDataConfirmed, setAgentDataConfirmed] = useState(false);
+
+ const apiKey = useGetOneEnrollmentAPIKey(selectedApiKeyId);
+ const apiKeyData = apiKey?.data;
+ const enrolledAgentIds = usePollingAgentCount(selectedPolicy?.id || '');
+
+ const fleetServerHosts = useMemo(() => {
+ return settings?.fleet_server_hosts || [];
+ }, [settings]);
+
+ const instructionsSteps = useMemo(() => {
+ const steps: EuiContainedStepProps[] = !agentPolicy
+ ? [
+ AgentPolicySelectionStep({
+ selectedPolicy,
+ agentPolicies,
+ selectedApiKeyId,
+ setSelectedAPIKeyId,
+ setSelectedPolicyId,
+ refreshAgentPolicies,
+ }),
+ ]
+ : [
+ AgentEnrollmentKeySelectionStep({
+ selectedPolicy,
+ selectedApiKeyId,
+ setSelectedAPIKeyId,
+ }),
+ ];
+
+ if (selectionType === 'radio') {
+ steps.push(InstallationModeSelectionStep({ mode, setMode }));
+ }
+
+ steps.push(
+ InstallManagedAgentStep({
+ apiKeyData,
+ selectedApiKeyId,
+ fleetServerHosts,
+ isK8s,
+ })
+ );
+ if (selectedApiKeyId && apiKeyData) {
+ steps.push(
+ AgentEnrollmentConfirmationStep({
+ selectedPolicyId: selectedPolicy?.id,
+ onClickViewAgents,
+ troubleshootLink: link,
+ agentCount: enrolledAgentIds.length,
+ })
+ );
+ }
+ if (selectedPolicy && enrolledAgentIds.length) {
+ steps.push(
+ IncomingDataConfirmationStep({
+ agentIds: enrolledAgentIds,
+ agentDataConfirmed,
+ setAgentDataConfirmed,
+ installedPolicy: installedPackagePolicy,
+ })
+ );
+ }
+
+ return steps;
+ }, [
+ agentPolicy,
+ selectedPolicy,
+ agentPolicies,
+ selectedApiKeyId,
+ setSelectedAPIKeyId,
+ setSelectedPolicyId,
+ refreshAgentPolicies,
+ selectionType,
+ apiKeyData,
+ fleetServerHosts,
+ isK8s,
+ mode,
+ setMode,
+ onClickViewAgents,
+ link,
+ enrolledAgentIds,
+ agentDataConfirmed,
+ installedPackagePolicy,
+ ]);
+
+ return ;
+};
+
+export const FleetServerSteps: React.FunctionComponent = ({
+ agentPolicy,
+ agentPolicies,
+ selectedPolicy,
+ setSelectedPolicyId,
+ refreshAgentPolicies,
+}) => {
+ const [selectedApiKeyId, setSelectedAPIKeyId] = useState();
+
+ const apiKey = useGetOneEnrollmentAPIKey(selectedApiKeyId);
+ const apiKeyData = apiKey?.data;
+ const fleetServerInstructions = useFleetServerInstructions(apiKeyData?.item?.policy_id);
+
+ const fleetServerSteps = useMemo(() => {
+ const {
+ serviceToken,
+ getServiceToken,
+ isLoadingServiceToken,
+ installCommand: managedInstallCommands,
+ platform,
+ setPlatform,
+ deploymentMode,
+ setDeploymentMode,
+ addFleetServerHost,
+ } = fleetServerInstructions;
+
+ return [
+ deploymentModeStep({ deploymentMode, setDeploymentMode }),
+ addFleetServerHostStep({ addFleetServerHost }),
+ ServiceTokenStep({ serviceToken, getServiceToken, isLoadingServiceToken }),
+ FleetServerCommandStep({
+ serviceToken,
+ installCommand: managedInstallCommands,
+ platform,
+ setPlatform,
+ }),
+ ];
+ }, [fleetServerInstructions]);
+
+ const instructionsSteps = useMemo(() => {
+ const steps: EuiContainedStepProps[] = !agentPolicy
+ ? [
+ AgentPolicySelectionStep({
+ selectedPolicy,
+ agentPolicies,
+ selectedApiKeyId,
+ setSelectedAPIKeyId,
+ setSelectedPolicyId,
+ refreshAgentPolicies,
+ }),
+ ]
+ : [
+ AgentEnrollmentKeySelectionStep({
+ selectedPolicy,
+ selectedApiKeyId,
+ setSelectedAPIKeyId,
+ }),
+ ];
+
+ steps.push(...fleetServerSteps);
+
+ return steps;
+ }, [
+ agentPolicy,
+ selectedPolicy,
+ agentPolicies,
+ selectedApiKeyId,
+ setSelectedPolicyId,
+ refreshAgentPolicies,
+ fleetServerSteps,
+ ]);
+
+ return ;
+};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/configure_standalone_agent_step.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/configure_standalone_agent_step.tsx
new file mode 100644
index 0000000000000..c0b64a88e19cc
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/configure_standalone_agent_step.tsx
@@ -0,0 +1,116 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import {
+ EuiText,
+ EuiButton,
+ EuiSpacer,
+ EuiCode,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiCopy,
+ EuiCodeBlock,
+} from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n-react';
+import { i18n } from '@kbn/i18n';
+
+import type { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps';
+
+import type { K8sMode } from '../types';
+
+export const ConfigureStandaloneAgentStep = ({
+ isK8s,
+ selectedPolicyId,
+ yaml,
+ downloadLink,
+}: {
+ isK8s?: K8sMode;
+ selectedPolicyId?: string;
+ yaml: string;
+ downloadLink: string;
+}): EuiContainedStepProps => {
+ const policyMsg =
+ isK8s === 'IS_KUBERNETES' ? (
+ ES_USERNAME,
+ ESPasswordVariable: ES_PASSWORD,
+ }}
+ />
+ ) : (
+ elastic-agent.yml,
+ ESUsernameVariable: ES_USERNAME,
+ ESPasswordVariable: ES_PASSWORD,
+ outputSection: outputs,
+ }}
+ />
+ );
+
+ const downloadMsg =
+ isK8s === 'IS_KUBERNETES' ? (
+
+ ) : (
+
+ );
+ return {
+ title: i18n.translate('xpack.fleet.agentEnrollment.stepConfigureAgentTitle', {
+ defaultMessage: 'Configure the agent',
+ }),
+ children: (
+ <>
+ {!yaml ? null : (
+
+ <>{policyMsg}>
+
+
+
+
+ {(copy) => (
+
+
+
+ )}
+
+
+
+
+ <>{downloadMsg}>
+
+
+
+
+
+ {yaml}
+
+
+ )}
+ >
+ ),
+ status: !yaml ? 'loading' : 'incomplete',
+ };
+};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/download_step.tsx
similarity index 67%
rename from x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps.tsx
rename to x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/download_step.tsx
index 54c449f74cc60..5004fc0a6444e 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/download_step.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import React, { useCallback, useEffect, useMemo, useState } from 'react';
+import React, { useEffect, useMemo, useState } from 'react';
import {
EuiText,
EuiButton,
@@ -22,21 +22,19 @@ import semverMajor from 'semver/functions/major';
import semverMinor from 'semver/functions/minor';
import semverPatch from 'semver/functions/patch';
-import type { AgentPolicy } from '../../types';
-import { useGetSettings, useKibanaVersion, useStartServices } from '../../hooks';
+import type { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps';
-import { agentPolicyRouteService } from '../../../common';
+import { useGetSettings, useKibanaVersion, useStartServices } from '../../../hooks';
-import { sendGetK8sManifest } from '../../hooks/use_request/k8s';
+import { agentPolicyRouteService } from '../../../../common';
-import { AdvancedAgentAuthenticationSettings } from './advanced_agent_authentication_settings';
-import { SelectCreateAgentPolicy } from './agent_policy_select_create';
+import { sendGetK8sManifest } from '../../../hooks/use_request/k8s';
export const DownloadStep = (
hasFleetServer: boolean,
isK8s?: string,
enrollmentAPIKey?: string
-) => {
+): EuiContainedStepProps => {
const kibanaVersion = useKibanaVersion();
const core = useStartServices();
const settings = useGetSettings();
@@ -49,6 +47,7 @@ export const DownloadStep = (
const [yaml, setYaml] = useState();
const [fleetServer, setFleetServer] = useState();
+
useEffect(() => {
async function fetchK8sManifest() {
try {
@@ -132,6 +131,7 @@ export const DownloadStep = (
) : (
''
);
+
const k8sCopyYaml =
isK8s === 'IS_KUBERNETES' ? (
@@ -147,6 +147,7 @@ export const DownloadStep = (
) : (
''
);
+
const k8sYaml =
isK8s === 'IS_KUBERNETES' ? (
@@ -202,96 +203,3 @@ export const DownloadStep = (
),
};
};
-
-export const AgentPolicySelectionStep = ({
- agentPolicies,
- setSelectedPolicyId,
- selectedApiKeyId,
- setSelectedAPIKeyId,
- excludeFleetServer,
- refreshAgentPolicies,
-}: {
- agentPolicies: AgentPolicy[];
- setSelectedPolicyId?: (policyId?: string) => void;
- selectedApiKeyId?: string;
- setSelectedAPIKeyId?: (key?: string) => void;
- excludeFleetServer?: boolean;
- refreshAgentPolicies: () => void;
-}) => {
- // storing the created agent policy id as the child component is being recreated
- const [policyId, setPolicyId] = useState(undefined);
- const regularAgentPolicies = useMemo(() => {
- return agentPolicies.filter(
- (policy) =>
- policy && !policy.is_managed && (!excludeFleetServer || !policy.is_default_fleet_server)
- );
- }, [agentPolicies, excludeFleetServer]);
-
- const onAgentPolicyChange = useCallback(
- async (key?: string, policy?: AgentPolicy) => {
- if (policy) {
- refreshAgentPolicies();
- }
- if (setSelectedPolicyId) {
- setSelectedPolicyId(key);
- setPolicyId(key);
- }
- },
- [setSelectedPolicyId, refreshAgentPolicies]
- );
-
- return {
- title: i18n.translate('xpack.fleet.agentEnrollment.stepChooseAgentPolicyTitle', {
- defaultMessage: 'What type of host are you adding?',
- }),
- children: (
- <>
-
- >
- ),
- };
-};
-
-export const AgentEnrollmentKeySelectionStep = ({
- agentPolicy,
- selectedApiKeyId,
- setSelectedAPIKeyId,
-}: {
- agentPolicy: AgentPolicy;
- selectedApiKeyId?: string;
- setSelectedAPIKeyId: (key?: string) => void;
-}) => {
- return {
- title: i18n.translate('xpack.fleet.agentEnrollment.stepConfigurePolicyAuthenticationTitle', {
- defaultMessage: 'Select enrollment token',
- }),
- children: (
- <>
-
- {agentPolicy.name},
- }}
- />
-
-
-
- >
- ),
- };
-};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/incoming_data_confirmation_step.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/incoming_data_confirmation_step.tsx
new file mode 100644
index 0000000000000..76cd1c07f4630
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/incoming_data_confirmation_step.tsx
@@ -0,0 +1,47 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { i18n } from '@kbn/i18n';
+
+import type { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps';
+
+import type { InstalledIntegrationPolicy } from '../use_get_agent_incoming_data';
+
+import { ConfirmIncomingData } from '../confirm_incoming_data';
+
+export const IncomingDataConfirmationStep = ({
+ agentIds,
+ installedPolicy,
+ agentDataConfirmed,
+ setAgentDataConfirmed,
+}: {
+ agentIds: string[];
+ installedPolicy?: InstalledIntegrationPolicy;
+ agentDataConfirmed: boolean;
+ setAgentDataConfirmed: (v: boolean) => void;
+}): EuiContainedStepProps => {
+ return {
+ title: !agentDataConfirmed
+ ? i18n.translate('xpack.fleet.agentEnrollment.stepConfirmIncomingData', {
+ defaultMessage: 'Confirm incoming data',
+ })
+ : i18n.translate('xpack.fleet.agentEnrollment.stepConfirmIncomingData.completed', {
+ defaultMessage: 'Incoming data confirmed',
+ }),
+ children: (
+
+ ),
+ status: !agentDataConfirmed ? 'loading' : 'complete',
+ };
+};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/index.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/index.tsx
new file mode 100644
index 0000000000000..53af0e66f7811
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/index.tsx
@@ -0,0 +1,17 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export * from './agent_enrollment_confirmation_step';
+export * from './agent_enrollment_key_selection_step';
+export * from './agent_policy_selection_step';
+export * from './configure_standalone_agent_step';
+export * from './download_step';
+export * from './incoming_data_confirmation_step';
+export * from './install_managed_agent_step';
+export * from './install_standalone_agent_step';
+export * from './installation_mode_selection_step';
+export * from './compute_steps';
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/install_managed_agent_step.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/install_managed_agent_step.tsx
new file mode 100644
index 0000000000000..03e8c305a6fcb
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/install_managed_agent_step.tsx
@@ -0,0 +1,41 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { i18n } from '@kbn/i18n';
+
+import type { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps';
+
+import type { GetOneEnrollmentAPIKeyResponse } from '../../../../common/types/rest_spec/enrollment_api_key';
+
+import { ManualInstructions } from '../../enrollment_instructions';
+
+export const InstallManagedAgentStep = ({
+ selectedApiKeyId,
+ apiKeyData,
+ fleetServerHosts,
+ isK8s,
+}: {
+ fleetServerHosts: string[];
+ selectedApiKeyId?: string;
+ apiKeyData?: GetOneEnrollmentAPIKeyResponse | null;
+ isK8s?: string;
+}): EuiContainedStepProps => {
+ return {
+ title: i18n.translate('xpack.fleet.agentEnrollment.stepEnrollAndRunAgentTitle', {
+ defaultMessage: 'Install Elastic Agent on your host',
+ }),
+ children: selectedApiKeyId && apiKeyData && (
+
+ ),
+ };
+};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/install_standalone_agent_step.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/install_standalone_agent_step.tsx
new file mode 100644
index 0000000000000..f1c6ce88233db
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/install_standalone_agent_step.tsx
@@ -0,0 +1,47 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+
+import type { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps';
+
+import type { CommandsByPlatform } from '../../../applications/fleet/sections/agents/agent_requirements_page/components/install_command_utils';
+import { PlatformSelector } from '../../enrollment_instructions/manual/platform_selector';
+
+import { InstallationMessage } from '../installation_message';
+
+import type { K8sMode } from '../types';
+
+export const InstallStandaloneAgentStep = ({
+ installCommand,
+ isK8s,
+ selectedPolicyId,
+}: {
+ installCommand: CommandsByPlatform;
+ isK8s?: K8sMode;
+ selectedPolicyId?: string;
+}): EuiContainedStepProps => {
+ return {
+ title: i18n.translate('xpack.fleet.agentEnrollment.stepEnrollAndRunAgentTitle', {
+ defaultMessage: 'Install Elastic Agent on your host',
+ }),
+ children: (
+ <>
+
+
+ >
+ ),
+ };
+};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/installation_mode_selection_step.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/installation_mode_selection_step.tsx
new file mode 100644
index 0000000000000..3864599fb6a94
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/installation_mode_selection_step.tsx
@@ -0,0 +1,88 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { EuiRadioGroup } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n-react';
+import { i18n } from '@kbn/i18n';
+
+import type { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps';
+
+import type { FlyoutMode } from '../types';
+
+export const InstallationModeSelectionStep = ({
+ mode,
+ setMode,
+}: {
+ mode: FlyoutMode;
+ setMode: (v: FlyoutMode) => void;
+}): EuiContainedStepProps => {
+ // radio id has to be unique so that the component works even if appears twice in DOM
+ const radioSuffix = 'installation_mode_agent_selection';
+
+ const onChangeCallback = (v: string) => {
+ const value = v.split('_')[0];
+ if (value === 'managed' || value === 'standalone') {
+ setMode(value);
+ }
+ };
+
+ return {
+ title: i18n.translate('xpack.fleet.agentEnrollment.stepInstallType', {
+ defaultMessage: 'Enroll in Fleet?',
+ }),
+ children: (
+
+
+
+ ),
+ }}
+ />
+ ),
+ },
+ {
+ id: `standalone_${radioSuffix}`,
+ label: (
+
+
+
+ ),
+ }}
+ />
+ ),
+ },
+ ]}
+ idSelected={`${mode}_${radioSuffix}`}
+ onChange={onChangeCallback}
+ name={`radio group ${radioSuffix}`}
+ />
+ ),
+ };
+};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/types.ts b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/types.ts
index edb34e876e7c8..0c2d9361aa3d6 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/types.ts
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/types.ts
@@ -5,35 +5,50 @@
* 2.0.
*/
-import type { EuiStepProps } from '@elastic/eui';
-
import type { AgentPolicy, Settings } from '../../types';
+import type { InstalledIntegrationPolicy } from './use_get_agent_incoming_data';
+
+export type K8sMode = 'IS_LOADING' | 'IS_KUBERNETES' | 'IS_NOT_KUBERNETES';
+export type FlyoutMode = 'managed' | 'standalone';
+export type SelectionType = 'tabs' | 'radio';
+
export interface BaseProps {
/**
* The user selected policy to be used. If this value is `undefined` a value must be provided for `agentPolicies`.
*/
agentPolicy?: AgentPolicy;
- /**
- * There is a step in the agent enrollment process that allows users to see the data from an integration represented in the UI
- * in some way. This is an area for consumers to render a button and text explaining how data can be viewed.
- */
- viewDataStep?: EuiStepProps;
-
settings?: Settings;
- setSelectedPolicyId?: (policyId?: string) => void;
+ isFleetServerPolicySelected?: boolean;
- policyId?: string;
+ isK8s?: K8sMode;
- isFleetServerPolicySelected?: boolean;
+ /**
+ * There is a step in the agent enrollment process that allows users to see the data from an integration represented in the UI
+ * in some way. This is an area for consumers to render a button and text explaining how data can be viewed.
+ */
+ isIntegrationFlow?: boolean;
+ installedPackagePolicy?: InstalledIntegrationPolicy;
+}
- isK8s?: string;
+export interface FlyOutProps extends BaseProps {
+ onClose: () => void;
+ defaultMode?: FlyoutMode;
}
export interface InstructionProps extends BaseProps {
agentPolicies: AgentPolicy[];
+ selectedPolicy: AgentPolicy | undefined;
+ setSelectedPolicyId: (policyId?: string) => void;
refreshAgentPolicies: () => void;
isLoadingAgentPolicies?: boolean;
+ onClickViewAgents: () => void;
+ mode: FlyoutMode;
+ setMode: (v: FlyoutMode) => void;
+ selectionType: SelectionType;
+ setSelectionType: (type: SelectionType) => void;
+ selectedApiKeyId?: string;
+ setSelectedAPIKeyId: (key?: string) => void;
}
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/use_get_agent_incoming_data.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/use_get_agent_incoming_data.tsx
new file mode 100644
index 0000000000000..4922a7d10c78c
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/use_get_agent_incoming_data.tsx
@@ -0,0 +1,121 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+import { useEffect, useState, useMemo, useRef } from 'react';
+import { i18n } from '@kbn/i18n';
+
+import type { IncomingDataList } from '../../../common/types/rest_spec/agent';
+
+import { sendGetAgentIncomingData, useLink } from '../../hooks/index';
+
+export interface InstalledIntegrationPolicy {
+ name: string;
+ version: string;
+}
+
+export const useGetAgentIncomingData = (
+ incomingData: IncomingDataList[],
+ installedPolicy?: InstalledIntegrationPolicy
+) => {
+ const enrolledAgents = useMemo(() => incomingData.length, [incomingData.length]);
+ const numAgentsWithData = useMemo(
+ () =>
+ incomingData.reduce((acc, curr) => {
+ const agentData = Object.values(curr)[0];
+ return !!agentData.data ? acc + 1 : acc;
+ }, 0),
+ [incomingData]
+ );
+ const { getAbsolutePath, getHref } = useLink();
+
+ let href;
+ let text;
+ let message;
+
+ if (!installedPolicy) {
+ href = '';
+ text = '';
+ message = '';
+ }
+
+ if (installedPolicy?.name === 'apm') {
+ href = getAbsolutePath('/app/home#/tutorial/apm');
+ text = i18n.translate('xpack.fleet.confirmIncomingData.installApmAgentButtonText', {
+ defaultMessage: 'Install APM Agent',
+ });
+ message = i18n.translate('xpack.fleet.confirmIncomingData.APMsubtitle', {
+ defaultMessage:
+ 'Next, install APM agents on your hosts to collect data from your applications and services.',
+ });
+ } else {
+ href = getHref('integration_details_assets', {
+ pkgkey: `${installedPolicy?.name}-${installedPolicy?.version}`,
+ });
+ text = i18n.translate('xpack.fleet.confirmIncomingData.viewDataAssetsButtonText', {
+ defaultMessage: 'View assets',
+ });
+ message = i18n.translate('xpack.fleet.confirmIncomingData.subtitle', {
+ defaultMessage:
+ 'Next, analyze your data using our integration assets such as curated views, dashboards and more.',
+ });
+ }
+ const linkButton = { href, text };
+
+ return {
+ enrolledAgents,
+ numAgentsWithData,
+ linkButton,
+ message,
+ };
+};
+
+/**
+ * Hook for polling incoming data for the selected agent policy.
+ * @param agentIds
+ * @returns incomingData, isLoading
+ */
+const POLLING_INTERVAL_MS = 5 * 1000; // 5 sec
+
+export const usePollingIncomingData = (agentsIds: string[]) => {
+ const timeout = useRef(undefined);
+ const [incomingData, setIncomingData] = useState([]);
+ const [isLoading, setIsLoading] = useState(true);
+
+ useEffect(() => {
+ let isAborted = false;
+
+ const poll = () => {
+ timeout.current = window.setTimeout(async () => {
+ const { data } = await sendGetAgentIncomingData({ agentsIds });
+
+ if (data?.items) {
+ // filter out agents that have `data = false` and keep polling
+ const filtered = data?.items.filter((item) => {
+ const key = Object.keys(item)[0];
+ return item[key].data === true;
+ });
+
+ if (filtered.length > 0) {
+ setIncomingData(filtered);
+ setIsLoading(false);
+ }
+ }
+ if (!isAborted) {
+ poll();
+ }
+ }, POLLING_INTERVAL_MS);
+ };
+
+ poll();
+ if (isAborted || incomingData.length > 0) clearTimeout(timeout.current);
+
+ return () => {
+ isAborted = true;
+ };
+ }, [agentsIds, incomingData]);
+
+ return { incomingData, isLoading };
+};
diff --git a/x-pack/plugins/fleet/public/components/enrollment_instructions/manual/index.tsx b/x-pack/plugins/fleet/public/components/enrollment_instructions/manual/index.tsx
index 020ca9dc053a7..077f9db0b05a2 100644
--- a/x-pack/plugins/fleet/public/components/enrollment_instructions/manual/index.tsx
+++ b/x-pack/plugins/fleet/public/components/enrollment_instructions/manual/index.tsx
@@ -7,15 +7,16 @@
import React from 'react';
-import { useStartServices, useKibanaVersion } from '../../../hooks';
+import { useKibanaVersion } from '../../../hooks';
import type { EnrollmentAPIKey } from '../../../types';
+import { InstallationMessage } from '../../agent_enrollment_flyout/installation_message';
+
import { PlatformSelector } from './platform_selector';
interface Props {
fleetServerHosts: string[];
apiKey: EnrollmentAPIKey;
- policyId: string | undefined;
isK8s: string | undefined;
}
@@ -26,10 +27,8 @@ function getfleetServerHostsEnrollArgs(apiKey: EnrollmentAPIKey, fleetServerHost
export const ManualInstructions: React.FunctionComponent = ({
apiKey,
fleetServerHosts,
- policyId,
isK8s,
}) => {
- const { docLinks } = useStartServices();
const enrollArgs = getfleetServerHostsEnrollArgs(apiKey, fleetServerHosts);
const kibanaVersion = useKibanaVersion();
@@ -57,14 +56,16 @@ sudo rpm -vi elastic-agent-${kibanaVersion}-x86_64.rpm
sudo elastic-agent enroll ${enrollArgs} \nsudo systemctl enable elastic-agent \nsudo systemctl start elastic-agent`;
return (
-
+ <>
+
+
+ >
);
};
diff --git a/x-pack/plugins/fleet/public/components/enrollment_instructions/manual/platform_selector.tsx b/x-pack/plugins/fleet/public/components/enrollment_instructions/manual/platform_selector.tsx
index 7fc1c827596e9..9551d9a7eae87 100644
--- a/x-pack/plugins/fleet/public/components/enrollment_instructions/manual/platform_selector.tsx
+++ b/x-pack/plugins/fleet/public/components/enrollment_instructions/manual/platform_selector.tsx
@@ -7,14 +7,7 @@
import React from 'react';
import styled from 'styled-components';
-import {
- EuiText,
- EuiSpacer,
- EuiLink,
- EuiCodeBlock,
- EuiButtonGroup,
- EuiCallOut,
-} from '@elastic/eui';
+import { EuiText, EuiSpacer, EuiCodeBlock, EuiButtonGroup, EuiCallOut } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { i18n } from '@kbn/i18n';
@@ -27,7 +20,6 @@ interface Props {
windowsCommand: string;
linuxDebCommand: string;
linuxRpmCommand: string;
- troubleshootLink: string;
isK8s: boolean;
}
@@ -44,7 +36,6 @@ export const PlatformSelector: React.FunctionComponent = ({
windowsCommand,
linuxDebCommand,
linuxRpmCommand,
- troubleshootLink,
isK8s,
}) => {
const { platform, setPlatform } = usePlatform();
@@ -127,23 +118,6 @@ export const PlatformSelector: React.FunctionComponent = ({
)}
>
)}
-
-
-
-
-
- ),
- }}
- />
-
>
);
};
diff --git a/x-pack/plugins/fleet/public/components/enrollment_instructions/standalone/index.tsx b/x-pack/plugins/fleet/public/components/enrollment_instructions/standalone/index.tsx
new file mode 100644
index 0000000000000..db36c16934e4b
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/enrollment_instructions/standalone/index.tsx
@@ -0,0 +1,51 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+import type { CommandsByPlatform } from '../../../applications/fleet/sections/agents/agent_requirements_page/components/install_command_utils';
+import type { K8sMode } from '../../../components/agent_enrollment_flyout/types';
+
+export const StandaloneInstructions = (
+ kibanaVersion: string,
+ isK8s?: K8sMode
+): CommandsByPlatform => {
+ const KUBERNETES_RUN_INSTRUCTIONS = 'kubectl apply -f elastic-agent-standalone-kubernetes.yaml';
+
+ const STANDALONE_RUN_INSTRUCTIONS_LINUX = `curl -L -O https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-${kibanaVersion}-linux-x86_64.tar.gz
+tar xzvf elastic-agent-${kibanaVersion}-linux-x86_64.tar.gz
+cd elastic-agent-${kibanaVersion}-linux-x86_64
+sudo ./elastic-agent install`;
+
+ const STANDALONE_RUN_INSTRUCTIONS_MAC = `curl -L -O https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-${kibanaVersion}-darwin-x86_64.tar.gz
+tar xzvf elastic-agent-${kibanaVersion}-darwin-x86_64.tar.gz
+cd elastic-agent-${kibanaVersion}-darwin-x86_64
+sudo ./elastic-agent install`;
+
+ const STANDALONE_RUN_INSTRUCTIONS_WINDOWS = `wget https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-${kibanaVersion}-windows-x86_64.zip -OutFile elastic-agent-${kibanaVersion}-windows-x86_64.zip
+Expand-Archive .\elastic-agent-${kibanaVersion}-windows-x86_64.zip
+cd elastic-agent-${kibanaVersion}-windows-x86_64
+.\\elastic-agent.exe install`;
+
+ const linuxDebCommand = `curl -L -O https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-${kibanaVersion}-amd64.deb
+ sudo dpkg -i elastic-agent-${kibanaVersion}-amd64.deb \nsudo systemctl enable elastic-agent \nsudo systemctl start elastic-agent`;
+
+ const linuxRpmCommand = `curl -L -O https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-${kibanaVersion}-x86_64.rpm
+ sudo rpm -vi elastic-agent-${kibanaVersion}-x86_64.rpm \nsudo systemctl enable elastic-agent \nsudo systemctl start elastic-agent`;
+
+ const linuxCommand =
+ isK8s === 'IS_KUBERNETES' ? KUBERNETES_RUN_INSTRUCTIONS : STANDALONE_RUN_INSTRUCTIONS_LINUX;
+ const macCommand =
+ isK8s === 'IS_KUBERNETES' ? KUBERNETES_RUN_INSTRUCTIONS : STANDALONE_RUN_INSTRUCTIONS_MAC;
+ const windowsCommand =
+ isK8s === 'IS_KUBERNETES' ? KUBERNETES_RUN_INSTRUCTIONS : STANDALONE_RUN_INSTRUCTIONS_WINDOWS;
+
+ return {
+ linux: linuxCommand,
+ mac: macCommand,
+ windows: windowsCommand,
+ deb: linuxDebCommand,
+ rpm: linuxRpmCommand,
+ };
+};
diff --git a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx
index 3338405c0b6c1..42b907cc282f4 100644
--- a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx
+++ b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx
@@ -7,7 +7,6 @@
import React, { useMemo, useState } from 'react';
import { EuiContextMenuItem, EuiPortal } from '@elastic/eui';
-import type { EuiStepProps } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import type { AgentPolicy, InMemoryPackagePolicy } from '../types';
@@ -22,14 +21,12 @@ import { PackagePolicyDeleteProvider } from './package_policy_delete_provider';
export const PackagePolicyActionsMenu: React.FunctionComponent<{
agentPolicy: AgentPolicy;
packagePolicy: InMemoryPackagePolicy;
- viewDataStep?: EuiStepProps;
showAddAgent?: boolean;
defaultIsOpen?: boolean;
upgradePackagePolicyHref: string;
}> = ({
agentPolicy,
packagePolicy,
- viewDataStep,
showAddAgent,
upgradePackagePolicyHref,
defaultIsOpen = false,
@@ -43,7 +40,6 @@ export const PackagePolicyActionsMenu: React.FunctionComponent<{
const onEnrollmentFlyoutClose = useMemo(() => {
return () => setIsEnrollmentFlyoutOpen(false);
}, []);
-
const menuItems = [
// FIXME: implement View package policy action
//
)}
diff --git a/x-pack/plugins/fleet/public/hooks/index.ts b/x-pack/plugins/fleet/public/hooks/index.ts
index c5dcdd78b9bb9..5c995131396b4 100644
--- a/x-pack/plugins/fleet/public/hooks/index.ts
+++ b/x-pack/plugins/fleet/public/hooks/index.ts
@@ -27,4 +27,3 @@ export * from './use_platform';
export * from './use_agent_policy_refresh';
export * from './use_package_installations';
export * from './use_agent_enrollment_flyout_data';
-export * from './use_get_agent_incoming_data';
diff --git a/x-pack/plugins/fleet/public/hooks/use_get_agent_incoming_data.tsx b/x-pack/plugins/fleet/public/hooks/use_get_agent_incoming_data.tsx
deleted file mode 100644
index a14dbd30aef45..0000000000000
--- a/x-pack/plugins/fleet/public/hooks/use_get_agent_incoming_data.tsx
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-import { useEffect, useState, useMemo } from 'react';
-import { i18n } from '@kbn/i18n';
-
-import type { IncomingDataList } from '../../common/types/rest_spec/agent';
-
-import { sendGetAgentIncomingData, useLink } from './index';
-
-export interface InstalledIntegrationPolicy {
- name: string;
- version: string;
-}
-
-export const useGetAgentIncomingData = (
- agentsIds: string[],
- installedPolicy?: InstalledIntegrationPolicy
-) => {
- const [isLoading, setIsLoading] = useState(true);
- const [incomingData, setIncomingData] = useState([]);
-
- useEffect(() => {
- const getIncomingData = async () => {
- const { data } = await sendGetAgentIncomingData({ agentsIds });
- if (data?.items) {
- setIncomingData(data?.items);
- setIsLoading(false);
- }
- };
- if (agentsIds) {
- getIncomingData();
- }
- }, [agentsIds]);
-
- const enrolledAgents = useMemo(() => incomingData.length, [incomingData.length]);
- const numAgentsWithData = useMemo(
- () =>
- incomingData.reduce((acc, curr) => {
- const agentData = Object.values(curr)[0];
- return !!agentData.data ? acc + 1 : acc;
- }, 0),
- [incomingData]
- );
- const { getAbsolutePath, getHref } = useLink();
-
- let href;
- let text;
- if (!installedPolicy) {
- href = '';
- text = '';
- }
-
- if (installedPolicy?.name === 'apm') {
- href = getAbsolutePath('/app/home#/tutorial/apm');
- text = i18n.translate('xpack.fleet.confirmIncomingData.installApmAgentButtonText', {
- defaultMessage: 'Install APM Agent',
- });
- } else {
- href = getHref('integration_details_assets', {
- pkgkey: `${installedPolicy?.name}-${installedPolicy?.version}`,
- });
- text = i18n.translate('xpack.fleet.confirmIncomingData.viewDataAssetsButtonText', {
- defaultMessage: 'View assets',
- });
- }
- const linkButton = { href, text };
-
- return {
- enrolledAgents,
- numAgentsWithData,
- isLoading,
- linkButton,
- };
-};
diff --git a/x-pack/plugins/fleet/public/hooks/use_platform.tsx b/x-pack/plugins/fleet/public/hooks/use_platform.tsx
index 286a685e89c84..6f8a41aba59e8 100644
--- a/x-pack/plugins/fleet/public/hooks/use_platform.tsx
+++ b/x-pack/plugins/fleet/public/hooks/use_platform.tsx
@@ -18,7 +18,7 @@ export const PLATFORM_OPTIONS: Array<{
{
id: 'linux',
label: i18n.translate('xpack.fleet.enrollmentInstructions.platformButtons.linux', {
- defaultMessage: 'Linux',
+ defaultMessage: 'Linux Tar',
}),
'data-test-subj': 'platformTypeLinux',
},
diff --git a/x-pack/plugins/fleet/server/services/agents/status.ts b/x-pack/plugins/fleet/server/services/agents/status.ts
index 828a3b1622cef..90113d1d177ef 100644
--- a/x-pack/plugins/fleet/server/services/agents/status.ts
+++ b/x-pack/plugins/fleet/server/services/agents/status.ts
@@ -144,7 +144,7 @@ export async function getIncomingDataByAgentsId(
agent_ids: {
terms: {
field: 'agent.id',
- size: 10,
+ size: agentsIds.length,
},
},
},
diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json
index b6cc88c5a8c92..687339109cbb0 100644
--- a/x-pack/plugins/translations/translations/fr-FR.json
+++ b/x-pack/plugins/translations/translations/fr-FR.json
@@ -9843,19 +9843,14 @@
"xpack.fleet.agentEnrollment.downloadLink": "Accéder à la page de téléchargement",
"xpack.fleet.agentEnrollment.downloadPolicyButton": "Télécharger la stratégie",
"xpack.fleet.agentEnrollment.downloadUseLinuxInstaller": "Utilisateurs de Linux : nous vous recommandons d'utiliser les programmes d'installation sur (RPM/DEB), car ils permettent la mise à niveau de votre agent dans Fleet.",
- "xpack.fleet.agentEnrollment.enrollFleetTabLabel": "Enregistrer dans Fleet",
- "xpack.fleet.agentEnrollment.enrollStandaloneTabLabel": "Exécuter de façon autonome",
"xpack.fleet.agentEnrollment.fleetSettingsLink": "Paramètres de Fleet",
"xpack.fleet.agentEnrollment.flyoutTitle": "Ajouter un agent",
- "xpack.fleet.agentEnrollment.goToDataStreamsLink": "flux de données",
"xpack.fleet.agentEnrollment.managedDescription": "L'enregistrement d'un agent Elastic Agent dans Fleet permet de centraliser la gestion de ce dernier tout en déployant automatiquement les mises à jour.",
"xpack.fleet.agentEnrollment.missingFleetHostCalloutText": "L'enregistrement d'agents dans Fleet nécessite l'URL de l'hôte de votre serveur Fleet. Vous pouvez ajouter ces informations dans Paramètres de Fleet. Pour en savoir plus, consultez {link}.",
"xpack.fleet.agentEnrollment.missingFleetHostCalloutTitle": "URL de l'hôte du serveur Fleet manquante",
"xpack.fleet.agentEnrollment.missingFleetHostGuideLink": "Guide de l'utilisateur de Fleet",
"xpack.fleet.agentEnrollment.setUpAgentsLink": "configurer la gestion centralisée des agents Elastic",
"xpack.fleet.agentEnrollment.standaloneDescription": "Exécutez un agent Elastic Agent de façon autonome pour le configurer et le mettre à jour manuellement sur l'hôte sur lequel il est installé.",
- "xpack.fleet.agentEnrollment.stepCheckForDataDescription": "L'agent devrait commencer à envoyer des données. Accédez à {link} pour consulter vos données.",
- "xpack.fleet.agentEnrollment.stepCheckForDataTitle": "Rechercher des données",
"xpack.fleet.agentEnrollment.stepChooseAgentPolicyTitle": "Sélectionner une stratégie d'agent",
"xpack.fleet.agentEnrollment.stepConfigureAgentDescription": "Copiez cette stratégie dans le fichier {fileName} de l'hôte sur lequel l'agent Elastic Agent est installé. Modifiez {ESUsernameVariable} et {ESPasswordVariable} dans la section {outputSection} du fichier {fileName} pour utiliser vos identifiants de connexion Elasticsearch.",
"xpack.fleet.agentEnrollment.stepConfigureAgentTitle": "Configurer l'agent",
@@ -9863,9 +9858,6 @@
"xpack.fleet.agentEnrollment.stepDownloadAgentTitle": "Télécharger l'agent Elastic Agent sur votre hôte",
"xpack.fleet.agentEnrollment.stepEnrollAndRunAgentTitle": "Enregistrer et démarrer l'agent Elastic Agent",
"xpack.fleet.agentEnrollment.stepRunAgentDescription": "Depuis le répertoire des agents, exécutez cette commande pour installer, enregistrer et démarrer un agent Elastic Agent. Vous pouvez réutiliser cette commande pour configurer des agents sur plusieurs hôtes. Cette action nécessite de disposer de privilèges d'administrateur.",
- "xpack.fleet.agentEnrollment.stepRunAgentTitle": "Démarrer l'agent",
- "xpack.fleet.agentEnrollment.stepViewDataTitle": "Consulter vos données",
- "xpack.fleet.agentEnrollment.viewDataDescription": "Une fois que votre agent a démarré, vous pouvez consulter vos données dans Kibana en utilisant les composants de l'intégration installés. {pleaseNote} : l'affichage des données initiales peut prendre quelques minutes.",
"xpack.fleet.agentHealth.checkInTooltipText": "Dernier archivage le {lastCheckIn}",
"xpack.fleet.agentHealth.healthyStatusText": "Sain",
"xpack.fleet.agentHealth.inactiveStatusText": "Inactif",
@@ -10133,8 +10125,6 @@
"xpack.fleet.enrollmentTokensList.secretTitle": "Secret",
"xpack.fleet.enrollmentTokensList.showTokenButtonLabel": "Afficher le jeton",
"xpack.fleet.epm.addPackagePolicyButtonText": "Ajouter {packageName}",
- "xpack.fleet.epm.agentEnrollment.viewDataAssetsLabel": "Voir les ressources",
- "xpack.fleet.epm.agentEnrollment.viewDataDescription.pleaseNoteLabel": "Remarque",
"xpack.fleet.epm.assetGroupTitle": "Ressources {assetType}",
"xpack.fleet.epm.browseAllButtonText": "Parcourir toutes les intégrations",
"xpack.fleet.epm.categoryLabel": "Catégorie",
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 45eff378b56f9..1527acb993bb4 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -11540,19 +11540,14 @@
"xpack.fleet.agentEnrollment.downloadPolicyButton": "ポリシーのダウンロード",
"xpack.fleet.agentEnrollment.downloadPolicyButtonk8s": "マニフェストのダウンロード",
"xpack.fleet.agentEnrollment.downloadUseLinuxInstaller": "Linuxユーザー:Fleetでエージェントをアップグレードできるため、システムパッケージ(RPM/DEB)ではインストーラー(TAR)をお勧めします。",
- "xpack.fleet.agentEnrollment.enrollFleetTabLabel": "Fleetで登録",
- "xpack.fleet.agentEnrollment.enrollStandaloneTabLabel": "スタンドアロンで実行",
"xpack.fleet.agentEnrollment.fleetSettingsLink": "Fleet設定",
"xpack.fleet.agentEnrollment.flyoutTitle": "エージェントの追加",
- "xpack.fleet.agentEnrollment.goToDataStreamsLink": "データストリーム",
"xpack.fleet.agentEnrollment.managedDescription": "ElasticエージェントをFleetに登録して、自動的に更新をデプロイしたり、一元的にエージェントを管理したりします。",
"xpack.fleet.agentEnrollment.missingFleetHostCalloutText": "Fleetにエージェントを登録するには、FleetサーバーホストのURLが必要です。Fleet設定でこの情報を追加できます。詳細は{link}をご覧ください。",
"xpack.fleet.agentEnrollment.missingFleetHostCalloutTitle": "FleetサーバーホストのURLが見つかりません",
"xpack.fleet.agentEnrollment.missingFleetHostGuideLink": "FleetおよびElasticエージェントガイド",
"xpack.fleet.agentEnrollment.setUpAgentsLink": "Elasticエージェントの集中管理を設定",
"xpack.fleet.agentEnrollment.standaloneDescription": "Elasticエージェントをスタンドアロンで実行して、エージェントがインストールされているホストで、手動でエージェントを構成および更新します。",
- "xpack.fleet.agentEnrollment.stepCheckForDataDescription": "エージェントがデータの送信を開始します。{link}に移動して、データを表示してください。",
- "xpack.fleet.agentEnrollment.stepCheckForDataTitle": "データを確認",
"xpack.fleet.agentEnrollment.stepChooseAgentPolicyTitle": "追加しているホストのタイプ",
"xpack.fleet.agentEnrollment.stepConfigureAgentDescription": "Elasticエージェントがインストールされているホストで、このポリシーを{fileName}にコピーします。Elasticsearch資格情報を使用するには、{fileName}の{outputSection}セクションで、{ESUsernameVariable}と{ESPasswordVariable}を変更します。",
"xpack.fleet.agentEnrollment.stepConfigureAgentDescriptionk8s": "Kubernetesクラスター内でKubernetesマニフェストをコピーしてダウンロードします。Daemonset環境変数で{ESUsernameVariable}と{ESPasswordVariable}を修正し、マニフェストを適用します。",
@@ -11563,9 +11558,6 @@
"xpack.fleet.agentEnrollment.stepEnrollAndRunAgentTitle": "Elasticエージェントを登録して実行",
"xpack.fleet.agentEnrollment.stepRunAgentDescription": "エージェントのディレクトリから、このコマンドを実行し、Elasticエージェントを、インストール、登録、起動します。このコマンドを再利用すると、複数のホストでエージェントを設定できます。管理者権限が必要です。",
"xpack.fleet.agentEnrollment.stepRunAgentDescriptionk8s": "Kubernetesマニフェストがダウンロードされるディレクトリから適用コマンドを実行します。",
- "xpack.fleet.agentEnrollment.stepRunAgentTitle": "エージェントの起動",
- "xpack.fleet.agentEnrollment.stepViewDataTitle": "データを表示",
- "xpack.fleet.agentEnrollment.viewDataDescription": "エージェントが起動した後、Kibanaでデータを表示するには、統合のインストールされたアセットを使用します。{pleaseNote}:初期データを受信するまでに数分かかる場合があります。",
"xpack.fleet.agentHealth.checkInTooltipText": "前回のチェックイン {lastCheckIn}",
"xpack.fleet.agentHealth.healthyStatusText": "正常",
"xpack.fleet.agentHealth.inactiveStatusText": "非アクティブ",
@@ -11864,8 +11856,6 @@
"xpack.fleet.epm.addPackagePolicyButtonPrivilegesRequiredTooltip": "Elasticエージェント統合には、Fleetの「すべて」権限と統合の「すべて」権限が必要です。管理者にお問い合わせください。",
"xpack.fleet.epm.addPackagePolicyButtonSecurityRequiredTooltip": "Elasticエージェント統合を追加するには、セキュリティを有効にし、Fleetの「すべて」権限が必要です。管理者にお問い合わせください。",
"xpack.fleet.epm.addPackagePolicyButtonText": "{packageName}の追加",
- "xpack.fleet.epm.agentEnrollment.viewDataAssetsLabel": "アセットを表示",
- "xpack.fleet.epm.agentEnrollment.viewDataDescription.pleaseNoteLabel": "注記:",
"xpack.fleet.epm.assetGroupTitle": "{assetType}アセット",
"xpack.fleet.epm.assetTitles.componentTemplates": "コンポーネントテンプレート",
"xpack.fleet.epm.assetTitles.dashboards": "ダッシュボード",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index ff9dfba86005e..70d58abb23a95 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -11559,19 +11559,14 @@
"xpack.fleet.agentEnrollment.downloadPolicyButton": "下载策略",
"xpack.fleet.agentEnrollment.downloadPolicyButtonk8s": "下载清单",
"xpack.fleet.agentEnrollment.downloadUseLinuxInstaller": "Linux 用户:我们建议使用安装程序 (TAR),而非系统软件包 (RPM/DEB),因为这允许您在 Fleet 中升级代理。",
- "xpack.fleet.agentEnrollment.enrollFleetTabLabel": "在 Fleet 中注册",
- "xpack.fleet.agentEnrollment.enrollStandaloneTabLabel": "独立运行",
"xpack.fleet.agentEnrollment.fleetSettingsLink": "Fleet 设置",
"xpack.fleet.agentEnrollment.flyoutTitle": "添加代理",
- "xpack.fleet.agentEnrollment.goToDataStreamsLink": "数据流",
"xpack.fleet.agentEnrollment.managedDescription": "在 Fleet 中注册 Elastic 代理,以便自动部署更新并集中管理该代理。",
"xpack.fleet.agentEnrollment.missingFleetHostCalloutText": "需要 Fleet 服务器主机的 URL,才能使用 Fleet 注册代理。可以在“Fleet 设置”中添加此信息。有关更多信息,请参阅{link}。",
"xpack.fleet.agentEnrollment.missingFleetHostCalloutTitle": "Fleet 服务器主机的 URL 缺失",
"xpack.fleet.agentEnrollment.missingFleetHostGuideLink": "Fleet 和 Elastic 代理指南",
"xpack.fleet.agentEnrollment.setUpAgentsLink": "为 Elastic 代理设置集中管理",
"xpack.fleet.agentEnrollment.standaloneDescription": "独立运行 Elastic 代理,以在安装代理的主机上手动配置和更新代理。",
- "xpack.fleet.agentEnrollment.stepCheckForDataDescription": "该代理应该开始发送数据。前往 {link} 以查看您的数据。",
- "xpack.fleet.agentEnrollment.stepCheckForDataTitle": "检查数据",
"xpack.fleet.agentEnrollment.stepChooseAgentPolicyTitle": "您正在添加什么类型的主机?",
"xpack.fleet.agentEnrollment.stepConfigureAgentDescription": "在安装 Elastic 代理的主机上将此策略复制到 {fileName}。在 {fileName} 的 {outputSection} 部分中修改 {ESUsernameVariable} 和 {ESPasswordVariable},以使用您的 Elasticsearch 凭据。",
"xpack.fleet.agentEnrollment.stepConfigureAgentDescriptionk8s": "复制或下载 Kubernetes 集群内的 Kubernetes 清单。修改 Daemonset 环境变量中的 {ESUsernameVariable} 和 {ESPasswordVariable} 并应用该清单。",
@@ -11582,9 +11577,6 @@
"xpack.fleet.agentEnrollment.stepEnrollAndRunAgentTitle": "注册并启动 Elastic 代理",
"xpack.fleet.agentEnrollment.stepRunAgentDescription": "从代理目录运行此命令,以安装、注册并启动 Elastic 代理。您可以重复使用此命令在多个主机上设置代理。需要管理员权限。",
"xpack.fleet.agentEnrollment.stepRunAgentDescriptionk8s": "从下载 Kubernetes 清单的目录运行应用命令。",
- "xpack.fleet.agentEnrollment.stepRunAgentTitle": "启动代理",
- "xpack.fleet.agentEnrollment.stepViewDataTitle": "查看您的数据",
- "xpack.fleet.agentEnrollment.viewDataDescription": "代理启动后,可以通过使用集成的已安装资产来在 Kibana 中查看数据。{pleaseNote}:获得初始数据可能需要几分钟。",
"xpack.fleet.agentHealth.checkInTooltipText": "上次签入时间 {lastCheckIn}",
"xpack.fleet.agentHealth.healthyStatusText": "运行正常",
"xpack.fleet.agentHealth.inactiveStatusText": "非活动",
@@ -11885,8 +11877,6 @@
"xpack.fleet.epm.addPackagePolicyButtonPrivilegesRequiredTooltip": "Elastic 代理集成需要 Fleet 的所有权限和集成的所有权限。请联系您的管理员。",
"xpack.fleet.epm.addPackagePolicyButtonSecurityRequiredTooltip": "要添加 Elastic 代理集成,必须启用安全功能并具有 Fleet 的所有权限。请联系您的管理员。",
"xpack.fleet.epm.addPackagePolicyButtonText": "添加 {packageName}",
- "xpack.fleet.epm.agentEnrollment.viewDataAssetsLabel": "查看资产",
- "xpack.fleet.epm.agentEnrollment.viewDataDescription.pleaseNoteLabel": "请注意",
"xpack.fleet.epm.assetGroupTitle": "{assetType} 资产",
"xpack.fleet.epm.assetTitles.componentTemplates": "组件模板",
"xpack.fleet.epm.assetTitles.dashboards": "仪表板",
From dcbf9daa0029134c71fe14488b630c980a718159 Mon Sep 17 00:00:00 2001
From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Date: Mon, 11 Apr 2022 11:38:23 -0500
Subject: [PATCH 06/75] skip failing test suite (#129785)
---
test/functional/apps/visualize/_tsvb_time_series.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/test/functional/apps/visualize/_tsvb_time_series.ts b/test/functional/apps/visualize/_tsvb_time_series.ts
index b474f2e68cb90..6180797cb886b 100644
--- a/test/functional/apps/visualize/_tsvb_time_series.ts
+++ b/test/functional/apps/visualize/_tsvb_time_series.ts
@@ -26,7 +26,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
const browser = getService('browser');
const kibanaServer = getService('kibanaServer');
- describe('visual builder', function describeIndexTests() {
+ // Failing: See https://github.com/elastic/kibana/issues/129785
+ describe.skip('visual builder', function describeIndexTests() {
before(async () => {
await security.testUser.setRoles([
'kibana_admin',
From 47b62d83af4823f94b03fae4190e56df8726baae Mon Sep 17 00:00:00 2001
From: Robert Austin
Date: Mon, 11 Apr 2022 12:42:33 -0400
Subject: [PATCH 07/75] Enhance Event Fields Browser performance (#129861)
* Enhance Event Fields Browser performance
* fixes checks
* Update x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.tsx
Use idiomatic value for EUI's `itemId` field
Co-authored-by: Jan Monschke
Co-authored-by: Gloria Hornero
Co-authored-by: Jan Monschke
---
.../event_details/event_fields_browser.tsx | 1 +
x-pack/plugins/timelines/public/plugin.ts | 14 ++++++++++++--
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.tsx
index 29700d3706b7b..e7547a8259514 100644
--- a/x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.tsx
@@ -279,6 +279,7 @@ export const EventFieldsBrowser = React.memo(
{
private _store: Store | undefined;
private _storage = new Storage(localStorage);
private _storeUnsubscribe: Unsubscribe | undefined;
+ private _hoverActions: HoverActionsConfig | undefined;
+
public setup(core: CoreSetup) {}
public start(core: CoreStart, { data }: TimelinesStartPlugins): TimelinesUIStart {
return {
+ /** `getHoverActions` returns a new reference to `getAddToTimelineButton` each time it is called, but that value is used in dependency arrays and so it should be as stable as possible. Therefore we lazily store the reference to it. Note: this reference is deleted when the store is changed. */
getHoverActions: () => {
- return getHoverActions(this._store);
+ if (this._hoverActions) {
+ return this._hoverActions;
+ } else {
+ this._hoverActions = getHoverActions(this._store);
+ return this._hoverActions;
+ }
},
getTGrid: (props: TGridProps) => {
if (props.type === 'standalone' && this._store) {
@@ -89,6 +97,8 @@ export class TimelinesPlugin implements Plugin {
private setStore(store: Store) {
this._store = store;
+ // this is lazily calculated and that is dependent on the store
+ delete this._hoverActions;
}
public stop() {
From 9b7cde9e6caf47b8b6a139c74a22713b14e2db41 Mon Sep 17 00:00:00 2001
From: gchaps <33642766+gchaps@users.noreply.github.com>
Date: Mon, 11 Apr 2022 09:43:06 -0700
Subject: [PATCH 08/75] [DOCS] Fixes formatting of settings (#129400)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
docs/setup/settings.asciidoc | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc
index c0b37ba9ec6f3..c8fa521f93947 100644
--- a/docs/setup/settings.asciidoc
+++ b/docs/setup/settings.asciidoc
@@ -689,29 +689,29 @@ sources and images. When false, Vega can only get data from {es}. *Default: `fal
| Enables you to view the underlying documents in a data series from a dashboard panel. *Default: `false`*
| `xpack.ilm.ui.enabled`
-Set this value to false to disable the Index Lifecycle Policies UI.
+ | Set this value to false to disable the Index Lifecycle Policies UI.
*Default: `true`*
| `xpack.index_management.ui.enabled`
-Set this value to false to disable the Index Management UI.
+ | Set this value to false to disable the Index Management UI.
*Default: `true`*
| `xpack.license_management.ui.enabled`
-Set this value to false to disable the License Management UI.
+ | Set this value to false to disable the License Management UI.
*Default: `true`*
| `xpack.remote_clusters.ui.enabled`
-Set this value to false to disable the Remote Clusters UI.
+ | Set this value to false to disable the Remote Clusters UI.
*Default: `true`*
| `xpack.rollup.ui.enabled:`
-Set this value to false to disable the Rollup Jobs UI. *Default: true*
+ | Set this value to false to disable the Rollup Jobs UI. *Default: true*
| `xpack.snapshot_restore.ui.enabled:`
-Set this value to false to disable the Snapshot and Restore UI. *Default: true*
+ | Set this value to false to disable the Snapshot and Restore UI. *Default: true*
| `xpack.upgrade_assistant.ui.enabled:`
-Set this value to false to disable the Upgrade Assistant UI. *Default: true*
+ | Set this value to false to disable the Upgrade Assistant UI. *Default: true*
| `i18n.locale` {ess-icon}
| Set this value to change the {kib} interface language.
From f032bbbf97b746f8c3b83f93144991d931d94f3d Mon Sep 17 00:00:00 2001
From: Andrea Del Rio
Date: Mon, 11 Apr 2022 09:55:03 -0700
Subject: [PATCH 09/75] [Discover] Add field types in-product help (#126657)
* added base popover
* add field types popover
* replace callout
* fix anchor
* use another euifilterbutton
* clean up table and add more field types
* [Discover] add pagination
* [Discover] show field types which are present in current data view, sort them alphabetically
* renaming
* more progress
* remove _source
* fix mobile view
* update icon
* [Discover] improve unit tests
* Scrolling instead of pagination
* i18n feedback
* cleanup
* Update src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx
Co-authored-by: Matthias Wilhelm
* Update discover_field_search.tsx
remove code that's unused
* add missing links
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Dzmitry Tamashevich
Co-authored-by: Dmitry Tomashevich <39378793+Dmitriynj@users.noreply.github.com>
Co-authored-by: cchaos
Co-authored-by: Matthias Wilhelm
Co-authored-by: Matthias Wilhelm
---
packages/kbn-doc-links/src/get_doc_links.ts | 3 +
.../sidebar/discover_field_search.scss | 12 +-
.../sidebar/discover_field_search.test.tsx | 30 +++-
.../sidebar/discover_field_search.tsx | 147 ++++++++++++++++--
.../components/sidebar/discover_sidebar.tsx | 26 +++-
.../discover_sidebar_responsive.test.tsx | 1 +
.../sidebar/lib/get_field_type_description.ts | 110 +++++++++++++
7 files changed, 308 insertions(+), 21 deletions(-)
create mode 100644 src/plugins/discover/public/application/main/components/sidebar/lib/get_field_type_description.ts
diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts
index 122486a1d0e9d..690765f3d0c4d 100644
--- a/packages/kbn-doc-links/src/get_doc_links.ts
+++ b/packages/kbn-doc-links/src/get_doc_links.ts
@@ -67,6 +67,9 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => {
discover: {
guide: `${KIBANA_DOCS}discover.html`,
fieldStatistics: `${KIBANA_DOCS}show-field-statistics.html`,
+ fieldTypeHelp: `${ELASTICSEARCH_DOCS}mapping-types.html`,
+ dateFieldTypeDocs: `${ELASTICSEARCH_DOCS}date.html`,
+ dateFormatsDocs: `${ELASTICSEARCH_DOCS}mapping-date-format.html`,
documentExplorer: `${KIBANA_DOCS}document-explorer.html`,
},
filebeat: {
diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.scss b/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.scss
index 4b620f2073771..59b6e49b0fe0e 100644
--- a/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.scss
+++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.scss
@@ -2,6 +2,14 @@
padding: $euiSizeM;
}
-.dscFieldSearch__filterWrapper {
- width: 100%;
+.dscFieldTypesHelp__popover {
+ flex-grow: 0;
+ min-width: 0 !important; // Reduce width of icon-only button
}
+
+.dscFieldTypesHelp__panel {
+ width: $euiSize * 22;
+ @include euiBreakpoint('xs', 's') {
+ width: $euiSize * 20;
+ }
+}
\ No newline at end of file
diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.test.tsx
index 40474f3e4fc1d..454f8620d7b08 100644
--- a/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.test.tsx
+++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.test.tsx
@@ -13,17 +13,25 @@ import { findTestSubject } from '@elastic/eui/lib/test';
import { DiscoverFieldSearch, Props } from './discover_field_search';
import { EuiButtonGroupProps, EuiPopover } from '@elastic/eui';
import { ReactWrapper } from 'enzyme';
+import { KibanaContextProvider } from '../../../../../../kibana_react/public';
describe('DiscoverFieldSearch', () => {
const defaultProps = {
onChange: jest.fn(),
value: 'test',
types: ['any', 'string', '_source'],
+ presentFieldTypes: ['string', 'date', 'boolean', 'number'],
};
function mountComponent(props?: Props) {
const compProps = props || defaultProps;
- return mountWithIntl();
+ return mountWithIntl(
+
+
+
+ );
}
function findButtonGroup(component: ReactWrapper, id: string) {
@@ -131,9 +139,25 @@ describe('DiscoverFieldSearch', () => {
const btn = findTestSubject(component, 'toggleFieldFilterButton');
btn.simulate('click');
let popover = component.find(EuiPopover);
- expect(popover.prop('isOpen')).toBe(true);
+ expect(popover.get(0).props.isOpen).toBe(true);
btn.simulate('click');
popover = component.find(EuiPopover);
- expect(popover.prop('isOpen')).toBe(false);
+ expect(popover.get(0).props.isOpen).toBe(false);
+ });
+
+ test('click help button should open popover with types of field docs', () => {
+ const component = mountComponent();
+
+ const btn = findTestSubject(component, 'fieldTypesHelpButton');
+ btn.simulate('click');
+ let popover = component.find(EuiPopover);
+ expect(popover.get(1).props.isOpen).toBe(true);
+
+ const rows = component.find('.euiTableRow');
+ expect(rows.length).toBe(4);
+
+ btn.simulate('click');
+ popover = component.find(EuiPopover);
+ expect(popover.get(1).props.isOpen).toBe(false);
});
});
diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.tsx
index 67282ea2667ed..f79e45059e87e 100644
--- a/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.tsx
+++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.tsx
@@ -8,9 +8,10 @@
import './discover_field_search.scss';
-import React, { OptionHTMLAttributes, ReactNode, useState } from 'react';
+import React, { OptionHTMLAttributes, ReactNode, useMemo, useState } from 'react';
import { i18n } from '@kbn/i18n';
import {
+ EuiBasicTable,
EuiFieldSearch,
EuiFilterGroup,
EuiFlexGroup,
@@ -24,11 +25,18 @@ import {
EuiForm,
EuiFormRow,
EuiButtonGroup,
- EuiOutsideClickDetector,
EuiFilterButton,
EuiSpacer,
+ EuiIcon,
+ EuiBasicTableColumn,
+ EuiLink,
+ EuiText,
+ EuiPanel,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
+import { FieldIcon } from '@kbn/react-field';
+import { GetFieldTypeDescription } from './lib/get_field_type_description';
+import { useDiscoverServices } from '../../../../utils/use_discover_services';
export interface State {
searchable: string;
@@ -43,23 +51,31 @@ export interface Props {
* triggered on input of user into search field
*/
onChange: (field: string, value: string | boolean | undefined) => void;
-
+ /**
+ * types for the type filter
+ */
+ types: string[];
+ /**
+ * types presented in current data view
+ */
+ presentFieldTypes: string[];
/**
* the input value of the user
*/
value?: string;
+}
- /**
- * types for the type filter
- */
- types: string[];
+interface FieldTypeTableItem {
+ id: number;
+ dataType: string;
+ description: string;
}
/**
* Component is Discover's side bar to search of available fields
* Additionally there's a button displayed that allows the user to show/hide more filter fields
*/
-export function DiscoverFieldSearch({ onChange, value, types }: Props) {
+export function DiscoverFieldSearch({ onChange, value, types, presentFieldTypes }: Props) {
const searchPlaceholder = i18n.translate('discover.fieldChooser.searchPlaceHolder', {
defaultMessage: 'Search field names',
});
@@ -80,6 +96,7 @@ export function DiscoverFieldSearch({ onChange, value, types }: Props) {
const [activeFiltersCount, setActiveFiltersCount] = useState(0);
const [isPopoverOpen, setPopoverOpen] = useState(false);
+ const [isHelpOpen, setIsHelpOpen] = useState(false);
const [values, setValues] = useState({
searchable: 'any',
aggregatable: 'any',
@@ -87,6 +104,43 @@ export function DiscoverFieldSearch({ onChange, value, types }: Props) {
missing: true,
});
+ const { docLinks } = useDiscoverServices();
+
+ const items: FieldTypeTableItem[] = useMemo(() => {
+ return presentFieldTypes
+ .sort((one, another) => one.localeCompare(another))
+ .map((element, index) => ({
+ id: index,
+ dataType: element,
+ description: GetFieldTypeDescription(element),
+ }));
+ }, [presentFieldTypes]);
+
+ const onHelpClick = () => setIsHelpOpen((prevIsHelpOpen) => !prevIsHelpOpen);
+ const closeHelp = () => setIsHelpOpen(false);
+
+ const columnsSidebar: Array> = [
+ {
+ field: 'dataType',
+ name: 'Data type',
+ width: '110px',
+ render: (name: string) => (
+
+
+
+
+ {name}
+
+ ),
+ },
+ {
+ field: 'description',
+ name: 'Description',
+ // eslint-disable-next-line react/no-danger
+ render: (description: string) => ,
+ },
+ ];
+
const filterBtnAriaLabel = isPopoverOpen
? i18n.translate('discover.fieldChooser.toggleFieldFilterButtonHideAriaLabel', {
defaultMessage: 'Hide field filter settings',
@@ -257,6 +311,26 @@ export function DiscoverFieldSearch({ onChange, value, types }: Props) {
);
+ const helpButton = (
+
+
+
+ );
+
return (
@@ -272,8 +346,8 @@ export function DiscoverFieldSearch({ onChange, value, types }: Props) {
- {}} isDisabled={!isPopoverOpen}>
-
+
+
+
+
+ {i18n.translate('discover.fieldChooser.popoverTitle', {
+ defaultMessage: 'Field types',
+ })}
+
+
+
+
+
+
+
+ {i18n.translate('discover.fieldTypesPopover.learnMoreText', {
+ defaultMessage: 'Learn more about',
+ })}
+
+
+
+
+
+
+
+
-
+
);
}
diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx
index 5b9f9a6c452d6..f3a3f121e36ad 100644
--- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx
+++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx
@@ -196,16 +196,31 @@ export function DiscoverSidebarComponent({
}
}, [paginate, scrollContainer, unpopularFields]);
- const fieldTypes = useMemo(() => {
+ const { fieldTypes, presentFieldTypes } = useMemo(() => {
const result = ['any'];
+ const dataViewFieldTypes = new Set();
if (Array.isArray(fields)) {
for (const field of fields) {
- if (result.indexOf(field.type) === -1) {
- result.push(field.type);
+ if (field.type !== '_source') {
+ // If it's a string type, we want to distinguish between keyword and text
+ // For this purpose we need the ES type
+ const type =
+ field.type === 'string' &&
+ field.esTypes &&
+ ['keyword', 'text'].includes(field.esTypes[0])
+ ? field.esTypes?.[0]
+ : field.type;
+ // _id and _index would map to string, that's why we don't add the string type here
+ if (type && type !== 'string') {
+ dataViewFieldTypes.add(type);
+ }
+ if (result.indexOf(field.type) === -1) {
+ result.push(field.type);
+ }
}
}
}
- return result;
+ return { fieldTypes: result, presentFieldTypes: Array.from(dataViewFieldTypes) };
}, [fields]);
const showFieldStats = useMemo(() => viewMode === VIEW_MODE.DOCUMENT_LEVEL, [viewMode]);
@@ -327,7 +342,7 @@ export function DiscoverSidebarComponent({
responsive={false}
>
-
+
diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx
index ef8fcd145c908..2adb1e5607a3b 100644
--- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx
+++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx
@@ -51,6 +51,7 @@ const mockServices = {
}
},
},
+ docLinks: { links: { discover: { fieldTypeHelp: '' } } },
} as unknown as DiscoverServices;
const mockfieldCounts: Record = {};
diff --git a/src/plugins/discover/public/application/main/components/sidebar/lib/get_field_type_description.ts b/src/plugins/discover/public/application/main/components/sidebar/lib/get_field_type_description.ts
new file mode 100644
index 0000000000000..69728787e7667
--- /dev/null
+++ b/src/plugins/discover/public/application/main/components/sidebar/lib/get_field_type_description.ts
@@ -0,0 +1,110 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { i18n } from '@kbn/i18n';
+import { useDiscoverServices } from '../../../../../utils/use_discover_services';
+
+export function GetFieldTypeDescription(type: string) {
+ const { docLinks } = useDiscoverServices();
+ switch (type) {
+ case 'boolean':
+ return i18n.translate('discover.fieldNameDescription.booleanField', {
+ defaultMessage: 'True and false values.',
+ });
+ case 'conflict':
+ return i18n.translate('discover.fieldNameDescription.conflictField', {
+ defaultMessage: 'Field has values of different types. Resolve in Management > Data Views.',
+ });
+ case 'date':
+ return i18n.translate('discover.fieldNameDescription.dateField', {
+ defaultMessage: 'A date string or the number of seconds or milliseconds since 1/1/1970.',
+ });
+ case 'date_range':
+ return i18n.translate('discover.fieldNameDescription.dateRangeField', {
+ defaultMessage: 'Range of {dateFieldTypeLink} values. {viewSupportedDateFormatsLink}',
+ values: {
+ dateFieldTypeLink:
+ `` +
+ i18n.translate('discover.fieldNameDescription.dateRangeFieldLinkText', {
+ defaultMessage: 'date',
+ }) +
+ '',
+ viewSupportedDateFormatsLink:
+ `` +
+ i18n.translate('discover.fieldNameDescription.viewSupportedDateFormatsLinkText', {
+ defaultMessage: 'View supported date formats.',
+ }) +
+ '',
+ },
+ });
+ case 'geo_point':
+ return i18n.translate('discover.fieldNameDescription.geoPointField', {
+ defaultMessage: 'Latitude and longitude points.',
+ });
+ case 'geo_shape':
+ return i18n.translate('discover.fieldNameDescription.geoShapeField', {
+ defaultMessage: 'Complex shapes, such as polygons.',
+ });
+ case 'ip':
+ return i18n.translate('discover.fieldNameDescription.ipAddressField', {
+ defaultMessage: 'IPv4 and IPv6 addresses.',
+ });
+ case 'ip_range':
+ return i18n.translate('discover.fieldNameDescription.ipAddressRangeField', {
+ defaultMessage: 'Range of ip values supporting either IPv4 or IPv6 (or mixed) addresses.',
+ });
+ case 'murmur3':
+ return i18n.translate('discover.fieldNameDescription.murmur3Field', {
+ defaultMessage: 'Field that computes and stores hashes of values.',
+ });
+ case 'number':
+ return i18n.translate('discover.fieldNameDescription.numberField', {
+ defaultMessage: 'Long, integer, short, byte, double, and float values.',
+ });
+ case 'string':
+ return i18n.translate('discover.fieldNameDescription.stringField', {
+ defaultMessage: 'Full text such as the body of an email or a product description.',
+ });
+ case 'text':
+ return i18n.translate('discover.fieldNameDescription.textField', {
+ defaultMessage: 'Full text such as the body of an email or a product description.',
+ });
+ case 'keyword':
+ return i18n.translate('discover.fieldNameDescription.keywordField', {
+ defaultMessage:
+ 'Structured content such as an ID, email address, hostname, status code, or tag.',
+ });
+
+ case 'nested':
+ return i18n.translate('discover.fieldNameDescription.nestedField', {
+ defaultMessage: 'JSON object that preserves the relationship between its subfields.',
+ });
+ case 'version':
+ return i18n.translate('discover.fieldNameDescription.versionField', {
+ defaultMessage: 'Software versions. Supports {SemanticVersioningLink} precedence rules.',
+ values: {
+ SemanticVersioningLink:
+ `` +
+ i18n.translate(
+ 'discover.advancedSettings.discover.fieldNameDescription.versionFieldLinkText',
+ {
+ defaultMessage: 'Semantic Versioning',
+ }
+ ) +
+ '',
+ },
+ });
+ default:
+ return i18n.translate('discover.fieldNameDescription.unknownField', {
+ defaultMessage: 'Unknown field',
+ });
+ }
+}
From 144a3c8313ba3ee58114ef65cc11ecc6e4522eb5 Mon Sep 17 00:00:00 2001
From: Paulo Henrique
Date: Mon, 11 Apr 2022 14:09:41 -0300
Subject: [PATCH 10/75] [Security Solution][Session View] Fix duplicated events
and runtime_fields that are no longer necessary on the Sessions Tab (#129835)
---
.../sessions_viewer/cell_renderer.tsx | 25 ++++++++++++
.../sessions_viewer/default_headers.ts | 10 +++--
.../components/sessions_viewer/index.tsx | 9 ++---
.../helpers/is_agg_cardinality_aggregate.ts | 19 +++++++++
.../server/search_strategy/timeline/index.ts | 40 +++++++++++++------
5 files changed, 81 insertions(+), 22 deletions(-)
create mode 100644 x-pack/plugins/security_solution/public/common/components/sessions_viewer/cell_renderer.tsx
create mode 100644 x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/is_agg_cardinality_aggregate.ts
diff --git a/x-pack/plugins/security_solution/public/common/components/sessions_viewer/cell_renderer.tsx b/x-pack/plugins/security_solution/public/common/components/sessions_viewer/cell_renderer.tsx
new file mode 100644
index 0000000000000..088935b32ce34
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/common/components/sessions_viewer/cell_renderer.tsx
@@ -0,0 +1,25 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { CellValueElementProps } from '../../../timelines/components/timeline/cell_rendering';
+import { DefaultCellRenderer } from '../../../timelines/components/timeline/cell_rendering/default_cell_renderer';
+import { getEmptyValue } from '../empty_value';
+import { MAPPED_PROCESS_END_COLUMN } from './default_headers';
+
+const hasEcsDataEndEventAction = (ecsData: CellValueElementProps['ecsData']) => {
+ return ecsData?.event?.action?.includes('end');
+};
+
+export const CellRenderer: React.FC = (props: CellValueElementProps) => {
+ // We only want to render process.end for event.actions of type 'end'
+ if (props.columnId === MAPPED_PROCESS_END_COLUMN && !hasEcsDataEndEventAction(props.ecsData)) {
+ return <>{getEmptyValue()}>;
+ }
+
+ return ;
+};
diff --git a/x-pack/plugins/security_solution/public/common/components/sessions_viewer/default_headers.ts b/x-pack/plugins/security_solution/public/common/components/sessions_viewer/default_headers.ts
index ee2f2e5452298..d73ab1b690f61 100644
--- a/x-pack/plugins/security_solution/public/common/components/sessions_viewer/default_headers.ts
+++ b/x-pack/plugins/security_solution/public/common/components/sessions_viewer/default_headers.ts
@@ -11,18 +11,20 @@ import { DEFAULT_DATE_COLUMN_MIN_WIDTH } from '../../../timelines/components/tim
import { SubsetTimelineModel } from '../../../timelines/store/timeline/model';
import { timelineDefaults } from '../../../timelines/store/timeline/defaults';
+// Using @timestamp as an way of getting the end time of the process. (Currently endpoint doesn't populate process.end)
+// @timestamp of an event.action with value of "end" is what we consider that to be the end time of the process
+// Current action are: 'start', 'exec', 'end', so we might have up to three events per process.
+export const MAPPED_PROCESS_END_COLUMN = '@timestamp';
+
export const sessionsHeaders: ColumnHeaderOptions[] = [
{
columnHeaderType: defaultColumnHeaderType,
id: 'process.start',
initialWidth: DEFAULT_DATE_COLUMN_MIN_WIDTH,
},
- // TODO: Using event.created as an way of getting the end time of the process. (Currently endpoint doesn't populate process.end)
- // event.created of a event.action with value of "end" is what we consider that to be the end time of the process
- // Current action are: 'start', 'exec', 'end', so we usually have three events per process.
{
columnHeaderType: defaultColumnHeaderType,
- id: 'event.created',
+ id: MAPPED_PROCESS_END_COLUMN,
display: 'process.end',
},
{
diff --git a/x-pack/plugins/security_solution/public/common/components/sessions_viewer/index.tsx b/x-pack/plugins/security_solution/public/common/components/sessions_viewer/index.tsx
index 3005d59bdc738..6834553a5eee8 100644
--- a/x-pack/plugins/security_solution/public/common/components/sessions_viewer/index.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/sessions_viewer/index.tsx
@@ -12,7 +12,7 @@ import { ESBoolQuery } from '../../../../common/typed_json';
import { StatefulEventsViewer } from '../events_viewer';
import { sessionsDefaultModel } from './default_headers';
import { defaultRowRenderers } from '../../../timelines/components/timeline/body/renderers';
-import { DefaultCellRenderer } from '../../../timelines/components/timeline/cell_rendering/default_cell_renderer';
+import { CellRenderer } from './cell_renderer';
import * as i18n from './translations';
import { SourcererScopeName } from '../../store/sourcerer/model';
import { getDefaultControlColumn } from '../../../timelines/components/timeline/body/control_columns';
@@ -28,8 +28,7 @@ export const defaultSessionsFilter: Required> = {
should: [
{
match: {
- // TODO: update to process.entry_leader.same_as_process once ECS is updated to support same_as_process
- 'process.is_entry_leader': true,
+ 'process.entry_leader.same_as_process': true,
},
},
],
@@ -42,7 +41,7 @@ export const defaultSessionsFilter: Required> = {
meta: {
alias: null,
disabled: false,
- key: 'process.is_entry_leader',
+ key: 'process.entry_leader.same_as_process',
negate: false,
params: {},
type: 'boolean',
@@ -96,7 +95,7 @@ const SessionsViewComponent: React.FC = ({
entityType={entityType}
id={timelineId}
leadingControlColumns={leadingControlColumns}
- renderCellValue={DefaultCellRenderer}
+ renderCellValue={CellRenderer}
rowRenderers={defaultRowRenderers}
scopeId={SourcererScopeName.default}
start={startDate}
diff --git a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/is_agg_cardinality_aggregate.ts b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/is_agg_cardinality_aggregate.ts
new file mode 100644
index 0000000000000..387d9c9a8ba26
--- /dev/null
+++ b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/is_agg_cardinality_aggregate.ts
@@ -0,0 +1,19 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+import {
+ AggregationsAggregate,
+ AggregationsCardinalityAggregate,
+} from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
+
+// type guard for checking if the Aggregation for a given field is a Cardinality
+// Agregate with valid value
+export const isAggCardinalityAggregate = (
+ aggregation: Record | undefined,
+ field: T
+): aggregation is Record => {
+ return (aggregation?.[field] as AggregationsCardinalityAggregate)?.value !== undefined;
+};
diff --git a/x-pack/plugins/timelines/server/search_strategy/timeline/index.ts b/x-pack/plugins/timelines/server/search_strategy/timeline/index.ts
index a5ef2f57888da..06f3b0e79b052 100644
--- a/x-pack/plugins/timelines/server/search_strategy/timeline/index.ts
+++ b/x-pack/plugins/timelines/server/search_strategy/timeline/index.ts
@@ -8,7 +8,6 @@
import { ALERT_RULE_CONSUMER, ALERT_RULE_TYPE_ID, SPACE_IDS } from '@kbn/rule-data-utils';
import { map, mergeMap, catchError } from 'rxjs/operators';
import { from } from 'rxjs';
-
import {
AlertingAuthorizationEntity,
AlertingAuthorizationFilterType,
@@ -28,6 +27,7 @@ import {
} from '../../../common/search_strategy/timeline';
import { timelineFactory } from './factory';
import { TimelineFactory } from './factory/types';
+import { isAggCardinalityAggregate } from './factory/helpers/is_agg_cardinality_aggregate';
import {
ENHANCED_ES_SEARCH_STRATEGY,
ISearchOptions,
@@ -205,29 +205,43 @@ const timelineSessionsSearchStrategy = ({
}) => {
const indices = request.defaultIndex ?? request.indexType;
- const runtimeMappings = {
- // TODO: remove once ECS is updated to support process.entry_leader.same_as_process
- 'process.is_entry_leader': {
- type: 'boolean',
- script: {
- source:
- "emit(doc.containsKey('process.entry_leader.entity_id') && doc['process.entry_leader.entity_id'].size() > 0 && doc['process.entity_id'].value == doc['process.entry_leader.entity_id'].value)",
- },
- },
- };
-
const requestSessionLeaders = {
...request,
defaultIndex: indices,
indexName: indices,
};
+ const collapse = {
+ field: 'process.entity_id',
+ inner_hits: {
+ name: 'last_event',
+ size: 1,
+ sort: [{ '@timestamp': 'desc' }],
+ },
+ };
+ const aggs = {
+ total: {
+ cardinality: {
+ field: 'process.entity_id',
+ },
+ },
+ };
+
const dsl = queryFactory.buildDsl(requestSessionLeaders);
- const params = { ...dsl, runtime_mappings: runtimeMappings };
+ const params = { ...dsl, collapse, aggs };
return es.search({ ...requestSessionLeaders, params }, options, deps).pipe(
map((response) => {
+ const agg = response.rawResponse.aggregations;
+ const aggTotal = isAggCardinalityAggregate(agg, 'total') && agg.total.value;
+
+ // ES doesn't set the hits.total to the collapsed hits.
+ // so we are overriding hits.total with the total from the aggregation.
+ if (aggTotal) {
+ response.rawResponse.hits.total = aggTotal;
+ }
+
return {
...response,
rawResponse: shimHitsTotal(response.rawResponse, options),
From f32faab84d1c60c045e8ad1d638105de7440302f Mon Sep 17 00:00:00 2001
From: Nick Peihl
Date: Mon, 11 Apr 2022 13:13:43 -0400
Subject: [PATCH 11/75] [DOCS] [Maps] Add documentation for custom icons
(#129530)
---
docs/maps/map-settings.asciidoc | 6 ++++++
docs/maps/vector-style-properties.asciidoc | 8 ++++++++
2 files changed, 14 insertions(+)
diff --git a/docs/maps/map-settings.asciidoc b/docs/maps/map-settings.asciidoc
index 21582c3e0c67f..5f353f99da375 100644
--- a/docs/maps/map-settings.asciidoc
+++ b/docs/maps/map-settings.asciidoc
@@ -5,6 +5,12 @@
Maps offers settings that let you configure how a map is displayed.
To access these settings, click *Map settings* in the application toolbar.
+[float]
+[[maps-settings-custom-icons]]
+=== Custom icons
+
+Add, edit, or delete custom icons for the map. Icons added to the map can be used for <>.
+
[float]
[[maps-settings-display]]
=== Display
diff --git a/docs/maps/vector-style-properties.asciidoc b/docs/maps/vector-style-properties.asciidoc
index ac06ba32e6e40..5bedfba28ada0 100644
--- a/docs/maps/vector-style-properties.asciidoc
+++ b/docs/maps/vector-style-properties.asciidoc
@@ -61,6 +61,14 @@ Available icons
[role="screenshot"]
image::maps/images/maki-icons.png[]
+Custom Icons
+
+You can also use your own SVG icon to style Point features in your map. In **Layer settings** open the *icon* dropdown, and click the **Add custom icon** button. For best results, your SVG icon should be monochrome and have limited details.
+
+Dynamic styling in **Elastic Maps** requires rendering SVG icons as PNGs using a https://en.wikipedia.org/wiki/Signed_distance_function[signed distance function]. As a result, sharp corners and intricate details may not render correctly. Modifying the settings under **Advanced Options** in the **Add custom icon** modal may improve rendering.
+
+Manage your custom icons in <>.
+
[float]
[[polygon-style-properties]]
==== Polygon style properties
From 1c72b56acb5c6a7215e4bba9406666b50f8a2f70 Mon Sep 17 00:00:00 2001
From: Diana Derevyankina
<54894989+DziyanaDzeraviankina@users.noreply.github.com>
Date: Mon, 11 Apr 2022 20:25:29 +0300
Subject: [PATCH 12/75] =?UTF-8?q?Failing=20test:=20Chrome=20UI=20Functiona?=
=?UTF-8?q?l=20Tests.test/functional/apps/visualize/=5Ftsvb=5Ftime=5Fserie?=
=?UTF-8?q?s=C2=B7ts=20-=20visualize=20app=20visualize=20ciGroup11=20visua?=
=?UTF-8?q?l=20builder=20Time=20Series=20basics=20Clicking=20on=20the=20ch?=
=?UTF-8?q?art=20should=20create=20a=20filter=20for=20series=20with=20mult?=
=?UTF-8?q?iple=20split=20by=20terms=20fields=20one=20of=20which=20has=20f?=
=?UTF-8?q?ormatting=20(#129840)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../apps/visualize/_tsvb_time_series.ts | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/test/functional/apps/visualize/_tsvb_time_series.ts b/test/functional/apps/visualize/_tsvb_time_series.ts
index 6180797cb886b..c27d2281d6119 100644
--- a/test/functional/apps/visualize/_tsvb_time_series.ts
+++ b/test/functional/apps/visualize/_tsvb_time_series.ts
@@ -11,11 +11,12 @@ import expect from '@kbn/expect';
import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ getPageObjects, getService }: FtrProviderContext) {
- const { visualize, visualBuilder, timeToVisualize, dashboard } = getPageObjects([
+ const { visualize, visualBuilder, timeToVisualize, dashboard, common } = getPageObjects([
'visualBuilder',
'visualize',
'timeToVisualize',
'dashboard',
+ 'common',
]);
const security = getService('security');
const testSubjects = getService('testSubjects');
@@ -186,14 +187,15 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await dashboard.waitForRenderComplete();
const el = await elasticChart.getCanvas();
- // click on specific coordinates
- await browser
- .getActions()
- .move({ x: 105, y: 115, origin: el._webElement })
- .click()
- .perform();
await retry.try(async () => {
+ // click on specific coordinates
+ await browser
+ .getActions()
+ .move({ x: 105, y: 115, origin: el._webElement })
+ .click()
+ .perform();
+ await common.sleep(2000);
await testSubjects.click('applyFiltersPopoverButton');
await testSubjects.missingOrFail('applyFiltersPopoverButton');
});
From 1c3aa7ae1e66c91fff6343e28bdbd6c84cbbc21c Mon Sep 17 00:00:00 2001
From: Maja Grubic
Date: Mon, 11 Apr 2022 20:28:07 +0200
Subject: [PATCH 13/75] [SharedUX] Migrate PageTemplate component (#129323)
* [SharedUX] Migrate PageTemplate > SolutionNavAvatar
* [SharedUX] Migrate PageTemplate > NoDataPage > ActionCards
* [SharedUX] Migrate PageTemplate > NoDataPage > SolutionNav
* Updating snapshot
* Fix i18n
* Fix index.tsx
* Fix failing test
* Remove unnecessary export
* Change folder structure of solution_nav_avatar
* [SharedUX] Migrate PageTemplate > NoDataPage > ActionCards
* [SharedUX] Migrate PageTemplate > NoDataPage > SolutionNav
* Updating snapshot
* Fix index.tsx
* Fix failing test
* Remove unnecessary export
* Fix comment
* Renaming component
* Fix folder structure
* Fix storybook
* Style fix
* Fix SolutionAvatar reference
* Fix failing test
* Fix failing snapshot
* Applying PR comments
* Updating failing snapshot
* Extract i18n
* collapsed > isCollapsed
* Applying PR comments
* NoDataConfigPage
* [SharedUX] Migrate PageTemplate
* Export component
* Quick design fixes
* Add pageHeader as a storybook prop
* Remove build additions
* Update .mdx file
* Merge two stories
* Applying Clint's comments
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: cchaos
---
.../kbn-shared-ux-components/src/index.ts | 17 ++
.../__snapshots__/page_template.test.tsx.snap | 197 ++++++++++++++++++
.../page_template_inner.test.tsx.snap | 85 ++++++++
.../with_solution_nav.test.tsx.snap | 125 +++++++++++
.../assets/kibana_template_no_data_config.png | 0
.../src/page_template/index.ts | 12 ++
.../src/page_template/no_data_page/index.ts | 1 +
.../no_data_config_page.test.tsx.snap | 31 +++
.../no_data_config_page}/index.tsx | 3 +-
.../no_data_config_page.test.tsx | 30 +++
.../no_data_config_page.tsx | 38 ++++
.../src/page_template/page_template.mdx | 168 +++++++++++++++
.../src/page_template/page_template.scss | 19 ++
.../page_template/page_template.stories.tsx | 143 +++++++++++++
.../src/page_template/page_template.test.tsx | 113 ++++++++++
.../src/page_template/page_template.tsx | 69 ++++++
.../page_template_inner.test.tsx | 67 ++++++
.../src/page_template/page_template_inner.tsx | 67 ++++++
.../src/page_template/types.ts | 30 +++
.../src/page_template/util/constants.ts | 21 ++
.../src/page_template/util/index.ts | 10 +
.../src/page_template/util/presentation.ts | 13 ++
.../page_template/with_solution_nav.test.tsx | 80 +++++++
.../src/page_template/with_solution_nav.tsx | 76 +++++++
24 files changed, 1413 insertions(+), 2 deletions(-)
create mode 100644 packages/kbn-shared-ux-components/src/page_template/__snapshots__/page_template.test.tsx.snap
create mode 100644 packages/kbn-shared-ux-components/src/page_template/__snapshots__/page_template_inner.test.tsx.snap
create mode 100644 packages/kbn-shared-ux-components/src/page_template/__snapshots__/with_solution_nav.test.tsx.snap
create mode 100644 packages/kbn-shared-ux-components/src/page_template/assets/kibana_template_no_data_config.png
create mode 100644 packages/kbn-shared-ux-components/src/page_template/index.ts
create mode 100644 packages/kbn-shared-ux-components/src/page_template/no_data_page/no_data_config_page/__snapshots__/no_data_config_page.test.tsx.snap
rename packages/kbn-shared-ux-components/src/page_template/{ => no_data_page/no_data_config_page}/index.tsx (76%)
create mode 100644 packages/kbn-shared-ux-components/src/page_template/no_data_page/no_data_config_page/no_data_config_page.test.tsx
create mode 100644 packages/kbn-shared-ux-components/src/page_template/no_data_page/no_data_config_page/no_data_config_page.tsx
create mode 100644 packages/kbn-shared-ux-components/src/page_template/page_template.mdx
create mode 100644 packages/kbn-shared-ux-components/src/page_template/page_template.scss
create mode 100644 packages/kbn-shared-ux-components/src/page_template/page_template.stories.tsx
create mode 100644 packages/kbn-shared-ux-components/src/page_template/page_template.test.tsx
create mode 100644 packages/kbn-shared-ux-components/src/page_template/page_template.tsx
create mode 100644 packages/kbn-shared-ux-components/src/page_template/page_template_inner.test.tsx
create mode 100644 packages/kbn-shared-ux-components/src/page_template/page_template_inner.tsx
create mode 100644 packages/kbn-shared-ux-components/src/page_template/types.ts
create mode 100644 packages/kbn-shared-ux-components/src/page_template/util/constants.ts
create mode 100644 packages/kbn-shared-ux-components/src/page_template/util/index.ts
create mode 100644 packages/kbn-shared-ux-components/src/page_template/util/presentation.ts
create mode 100644 packages/kbn-shared-ux-components/src/page_template/with_solution_nav.test.tsx
create mode 100644 packages/kbn-shared-ux-components/src/page_template/with_solution_nav.tsx
diff --git a/packages/kbn-shared-ux-components/src/index.ts b/packages/kbn-shared-ux-components/src/index.ts
index a022d2d0c755d..e6e72b23c3d17 100644
--- a/packages/kbn-shared-ux-components/src/index.ts
+++ b/packages/kbn-shared-ux-components/src/index.ts
@@ -95,6 +95,23 @@ export const LazyIconButtonGroup = React.lazy(() =>
*/
export const IconButtonGroup = withSuspense(LazyIconButtonGroup);
+/**
+ * The lazily loaded `KibanaPageTemplate` component that is wrapped by the `withSuspense` HOC. Consumers should use
+ * `React.Suspense` or `withSuspense` HOC to load this component.
+ */
+export const KibanaPageTemplateLazy = React.lazy(() =>
+ import('./page_template').then(({ KibanaPageTemplate }) => ({
+ default: KibanaPageTemplate,
+ }))
+);
+
+/**
+ * A `KibanaPageTemplate` component that is wrapped by the `withSuspense` HOC. This component can
+ * be used directly by consumers and will load the `KibanaPageTemplateLazy` component lazily with
+ * a predefined fallback and error boundary.
+ */
+export const KibanaPageTemplate = withSuspense(KibanaPageTemplateLazy);
+
/**
* The lazily loaded `KibanaPageTemplateSolutionNav` component that is wrapped by the `withSuspense` HOC. Consumers should use
* `React.Suspense` or `withSuspense` HOC to load this component.
diff --git a/packages/kbn-shared-ux-components/src/page_template/__snapshots__/page_template.test.tsx.snap b/packages/kbn-shared-ux-components/src/page_template/__snapshots__/page_template.test.tsx.snap
new file mode 100644
index 0000000000000..e41292f549c99
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/__snapshots__/page_template.test.tsx.snap
@@ -0,0 +1,197 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`KibanaPageTemplate render basic template 1`] = `
+
+`;
+
+exports[`KibanaPageTemplate render noDataConfig && solutionNav 1`] = `
+
+`;
+
+exports[`KibanaPageTemplate render noDataConfig 1`] = `
+
+`;
+
+exports[`KibanaPageTemplate render solutionNav 1`] = `
+
+
+ Child element
+
+
+`;
diff --git a/packages/kbn-shared-ux-components/src/page_template/__snapshots__/page_template_inner.test.tsx.snap b/packages/kbn-shared-ux-components/src/page_template/__snapshots__/page_template_inner.test.tsx.snap
new file mode 100644
index 0000000000000..ef665dff6fe6d
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/__snapshots__/page_template_inner.test.tsx.snap
@@ -0,0 +1,85 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`KibanaPageTemplateInner custom template 1`] = `
+
+
+ test
+
+ }
+ iconColor=""
+ iconType="test"
+ title={
+
+ test
+
+ }
+ />
+
+`;
+
+exports[`KibanaPageTemplateInner isEmpty no pageHeader 1`] = `
+
+`;
+
+exports[`KibanaPageTemplateInner isEmpty pageHeader & children 1`] = `
+
+
+ Child element
+
+
+`;
+
+exports[`KibanaPageTemplateInner isEmpty pageHeader & no children 1`] = `
+
+
+ test
+
+ }
+ iconColor=""
+ iconType="test"
+ title={
+
+ test
+
+ }
+ />
+
+`;
diff --git a/packages/kbn-shared-ux-components/src/page_template/__snapshots__/with_solution_nav.test.tsx.snap b/packages/kbn-shared-ux-components/src/page_template/__snapshots__/with_solution_nav.test.tsx.snap
new file mode 100644
index 0000000000000..0064b0a638cd2
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/__snapshots__/with_solution_nav.test.tsx.snap
@@ -0,0 +1,125 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`WithSolutionNav renders wrapped component 1`] = `
+
+ }
+ pageSideBarProps={
+ Object {
+ "className": "kbnPageTemplate__pageSideBar",
+ "paddingSize": "none",
+ }
+ }
+/>
+`;
+
+exports[`WithSolutionNav with children 1`] = `
+
+ }
+ pageSideBarProps={
+ Object {
+ "className": "kbnPageTemplate__pageSideBar",
+ "paddingSize": "none",
+ }
+ }
+>
+
+ Child component
+
+
+`;
diff --git a/packages/kbn-shared-ux-components/src/page_template/assets/kibana_template_no_data_config.png b/packages/kbn-shared-ux-components/src/page_template/assets/kibana_template_no_data_config.png
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/packages/kbn-shared-ux-components/src/page_template/index.ts b/packages/kbn-shared-ux-components/src/page_template/index.ts
new file mode 100644
index 0000000000000..caed703e5d656
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/index.ts
@@ -0,0 +1,12 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+export { NoDataCard, ElasticAgentCard } from './no_data_page';
+export { NoDataPage } from './no_data_page';
+export { KibanaPageTemplate } from './page_template';
+export type { KibanaPageTemplateProps } from './types';
diff --git a/packages/kbn-shared-ux-components/src/page_template/no_data_page/index.ts b/packages/kbn-shared-ux-components/src/page_template/no_data_page/index.ts
index c1b0ac2e13395..894097727cd1f 100644
--- a/packages/kbn-shared-ux-components/src/page_template/no_data_page/index.ts
+++ b/packages/kbn-shared-ux-components/src/page_template/no_data_page/index.ts
@@ -9,3 +9,4 @@
export { NoDataCard, ElasticAgentCard } from './no_data_card';
export { NoDataPage } from './no_data_page';
export type { NoDataPageProps } from './types';
+export { NoDataConfigPage, NoDataConfigPageWithSolutionNavBar } from './no_data_config_page';
diff --git a/packages/kbn-shared-ux-components/src/page_template/no_data_page/no_data_config_page/__snapshots__/no_data_config_page.test.tsx.snap b/packages/kbn-shared-ux-components/src/page_template/no_data_page/no_data_config_page/__snapshots__/no_data_config_page.test.tsx.snap
new file mode 100644
index 0000000000000..047f44e0d319c
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/no_data_page/no_data_config_page/__snapshots__/no_data_config_page.test.tsx.snap
@@ -0,0 +1,31 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`NoDataConfigPage renders 1`] = `
+
+
+
+`;
diff --git a/packages/kbn-shared-ux-components/src/page_template/index.tsx b/packages/kbn-shared-ux-components/src/page_template/no_data_page/no_data_config_page/index.tsx
similarity index 76%
rename from packages/kbn-shared-ux-components/src/page_template/index.tsx
rename to packages/kbn-shared-ux-components/src/page_template/no_data_page/no_data_config_page/index.tsx
index d469a2fb34c10..0bdde40021398 100644
--- a/packages/kbn-shared-ux-components/src/page_template/index.tsx
+++ b/packages/kbn-shared-ux-components/src/page_template/no_data_page/no_data_config_page/index.tsx
@@ -6,5 +6,4 @@
* Side Public License, v 1.
*/
-export { NoDataCard, ElasticAgentCard } from './no_data_page';
-export { NoDataPage } from './no_data_page';
+export { NoDataConfigPage, NoDataConfigPageWithSolutionNavBar } from './no_data_config_page';
diff --git a/packages/kbn-shared-ux-components/src/page_template/no_data_page/no_data_config_page/no_data_config_page.test.tsx b/packages/kbn-shared-ux-components/src/page_template/no_data_page/no_data_config_page/no_data_config_page.test.tsx
new file mode 100644
index 0000000000000..dc618a068e120
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/no_data_page/no_data_config_page/no_data_config_page.test.tsx
@@ -0,0 +1,30 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { shallow } from 'enzyme';
+import React from 'react';
+import { NoDataConfigPage } from './no_data_config_page';
+
+describe('NoDataConfigPage', () => {
+ const noDataConfig = {
+ solution: 'Kibana',
+ logo: 'logoKibana',
+ docsLink: 'test-link',
+ action: {
+ kibana: {
+ button: 'Click me',
+ onClick: jest.fn(),
+ description: 'Page with no data',
+ },
+ },
+ };
+ test('renders', () => {
+ const component = shallow();
+ expect(component).toMatchSnapshot();
+ });
+});
diff --git a/packages/kbn-shared-ux-components/src/page_template/no_data_page/no_data_config_page/no_data_config_page.tsx b/packages/kbn-shared-ux-components/src/page_template/no_data_page/no_data_config_page/no_data_config_page.tsx
new file mode 100644
index 0000000000000..77c2d659b56ef
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/no_data_page/no_data_config_page/no_data_config_page.tsx
@@ -0,0 +1,38 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+import { EuiPageTemplate } from '@elastic/eui';
+import React from 'react';
+import { NoDataPage } from '../no_data_page';
+import { withSolutionNav } from '../../with_solution_nav';
+import { KibanaPageTemplateProps } from '../../types';
+import { getClasses, NO_DATA_PAGE_TEMPLATE_PROPS } from '../../util';
+
+export const NoDataConfigPage = (props: KibanaPageTemplateProps) => {
+ const { className, noDataConfig, ...rest } = props;
+
+ if (!noDataConfig) {
+ return null;
+ }
+
+ const template = NO_DATA_PAGE_TEMPLATE_PROPS.template;
+ const classes = getClasses(template, className);
+
+ return (
+
+
+
+ );
+};
+
+export const NoDataConfigPageWithSolutionNavBar = withSolutionNav(NoDataConfigPage);
diff --git a/packages/kbn-shared-ux-components/src/page_template/page_template.mdx b/packages/kbn-shared-ux-components/src/page_template/page_template.mdx
new file mode 100644
index 0000000000000..59acf8910cf29
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/page_template.mdx
@@ -0,0 +1,168 @@
+---
+id: sharedUX/Components/PageTemplate
+slug: /shared-ux-components/page_template/page_template
+title: Page Template
+summary: A Kibana-specific wrapper around `EuiTemplate`
+tags: ['shared-ux', 'component']
+date: 2022-04-04
+---
+
+`KibanaPageTemplate` is a thin wrapper around [EuiPageTemplate](https://elastic.github.io/eui/#/layout/page) that makes setting up common types of Kibana pages quicker and easier while also adhering to any Kibana-specific requirements and patterns.
+
+Refer to EUI's documentation on [**EuiPageTemplate**](https://elastic.github.io/eui/#/layout/page) for constructing page layouts.
+
+## `isEmptyState`
+
+Use the `isEmptyState` prop for when there is no page content to show. For example, before the user has created something, when no search results are found, before data is populated, or when permissions aren't met.
+
+The default empty state uses any `pageHeader` info provided to populate an [**EuiEmptyPrompt**](https://elastic.github.io/eui/#/display/empty-prompt) and uses the `centeredBody` template type.
+
+```tsx
+
+ Create new dashboard
+ ,
+ ],
+ }}
+/>
+```
+
+![Screenshot of demo empty state code. Shows the Kibana navigation bars and a centered empty state with the dashboard app icon, a level 1 heading "Dashboards", body text "You don't have any dashboards yet.", and a button that says "Create new dashboard".](https://raw.githubusercontent.com/elastic/kibana/main/dev_docs/assets/kibana_default_empty_state.png)
+
+
+ Because all properties of the page header are optional, the empty state has the potential to
+ render blank. Make sure your empty state doesn't leave the user confused.
+
+
+
+### Custom empty state
+
+You can also provide a custom empty prompt to replace the pre-built one. You'll want to remove any `pageHeader` props and pass an [`EuiEmptyPrompt`](https://elastic.github.io/eui/#/display/empty-prompt) directly as the child of KibanaPageTemplate.
+
+```tsx
+
+ No data}
+ body="You have no data. Would you like some of ours?"
+ actions={[
+
+ Get sample data
+ ,
+ ]}
+ />
+
+```
+
+![Screenshot of demo custom empty state code. Shows the Kibana navigation bars and a centered empty state with the a level 1 heading "No data", body text "You have no data. Would you like some of ours?", and a button that says "Get sample data".](https://raw.githubusercontent.com/elastic/kibana/main/dev_docs/assets/kibana_custom_empty_state.png)
+
+### Empty states with a page header
+
+When passing both a `pageHeader` configuration and `isEmptyState`, the component will render the proper template (`centeredContent`). Be sure to reduce the heading level within your child empty prompt to ``.
+
+```tsx
+
+ No data
}
+ body="You have no data. Would you like some of ours?"
+ actions={[
+
+ Get sample data
+ ,
+ ]}
+ />
+
+```
+
+![Screenshot of demo custom empty state code with a page header. Shows the Kibana navigation bars, a level 1 heading "Dashboards", and a centered empty state with the a level 2 heading "No data", body text "You have no data. Would you like some of ours?", and a button that says "Get sample data".](https://raw.githubusercontent.com/elastic/kibana/main/dev_docs/assets/kibana_header_and_empty_state.png)
+
+## `solutionNav`
+
+To add left side navigation for your solution, we recommend passing [**EuiSideNav**](https://elastic.github.io/eui/#/navigation/side-nav) props to the `solutionNav` prop. The template component will then handle the mobile views and add the solution nav embellishments. On top of the EUI props, you'll need to pass your solution `name` and an optional `icon`.
+
+If you need to custom side bar content, you will need to pass you own navigation component to `pageSideBar`. We still recommend using [**EuiSideNav**](https://elastic.github.io/eui/#/navigation/side-nav).
+
+When using `EuiSideNav`, root level items should not be linked but provide section labelling only.
+
+```tsx
+
+ {...}
+
+```
+
+![Screenshot of Stack Management empty state with a provided solution navigation shown on the left, outlined in pink.](https://raw.githubusercontent.com/elastic/kibana/main/dev_docs/assets/kibana_template_solution_nav.png)
+
+![Screenshots of Stack Management page in mobile view. Menu closed on the left, menu open on the right.](https://raw.githubusercontent.com/elastic/kibana/main/dev_docs/assets/kibana_template_solution_nav_mobile.png)
+
+## `noDataConfig`
+
+Increases the consistency in messaging across all the solutions during the getting started process when no data exists. Each solution/template instance decides when is the most appropriate time to show this configuration, but is messaged specifically towards having no indices or index patterns at all or that match the particular solution.
+
+This is a built-in configuration that displays a very specific UI and requires very specific keys. It will also ignore all other configurations of the template including `pageHeader` and `children`, with the exception of continuing to show `solutionNav`.
+
+The `noDataConfig` is of type [`NoDataPageProps`](https://github.com/elastic/kibana/blob/main/packages/kbn-shared-ux-components/src/page_template/no_data_page/types.ts#L14):
+
+1. `solution: string`: Single name for the current solution, used to auto-generate the title, logo, and description *(required)*
+2. `docsLink: string`: Required to set the docs link for the whole solution *(required)*
+3. `logo?: string`: Optionally replace the auto-generated logo
+4. `pageTitle?: string`: Optionally replace the auto-generated page title (h1)
+5. `action: Record`: An object of `NoDataPageActions` configurations with a unique primary key *(required)*
+
+### `NoDataPageActions`
+
+There is a main action for adding data that we promote throughout Kibana - Elastic Agent. It is added to the card by using the key `elasticAgent`. For consistent messaging, this card is pre-configured but requires specific `href`s and/or `onClick` handlers for directing the user to the right location for that solution.
+
+Optionally you can also replace the `button` label by passing a string, or the whole component by passing a `ReactNode`.
+
+
+```tsx
+// Perform your own check
+const hasData = checkForData();
+
+// No data configuration
+const noDataConfig: KibanaPageTemplateProps['noDataConfig'] = {
+ solution: 'Analytics',
+ logo: 'logoKibana',
+ docsLink: '#',
+ action: {
+ elasticAgent: {
+ href: '#',
+ },
+ },
+};
+
+// Conditionally apply the configuration if there is no data
+
+ {/* Children will be ignored */}
+
+```
+
+![Screenshot of and example in Observability using the no data configuration and using the corresponding list numbers to point out the UI elements that they adjust.](https://raw.githubusercontent.com/elastic/kibana/main/dev_docs/assets/kibana_template_no_data_config.png)
\ No newline at end of file
diff --git a/packages/kbn-shared-ux-components/src/page_template/page_template.scss b/packages/kbn-shared-ux-components/src/page_template/page_template.scss
new file mode 100644
index 0000000000000..aec93da6217ee
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/page_template.scss
@@ -0,0 +1,19 @@
+.kbnPageTemplate__pageSideBar {
+ overflow: hidden;
+ // Temporary hack till the sizing is changed directly in EUI
+ min-width: 248px;
+
+ @include euiCanAnimate {
+ transition: min-width $euiAnimSpeedFast $euiAnimSlightResistance;
+ }
+
+ &.kbnPageTemplate__pageSideBar--shrink {
+ min-width: $euiSizeXXL;
+ }
+
+ .kbnPageTemplate--centeredBody & {
+ @include euiBreakpoint('m', 'l', 'xl') {
+ border-right: $euiBorderThin;
+ }
+ }
+}
diff --git a/packages/kbn-shared-ux-components/src/page_template/page_template.stories.tsx b/packages/kbn-shared-ux-components/src/page_template/page_template.stories.tsx
new file mode 100644
index 0000000000000..d840e459389b2
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/page_template.stories.tsx
@@ -0,0 +1,143 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React from 'react';
+import { EuiButton, EuiText } from '@elastic/eui';
+import { KibanaPageTemplate } from './page_template';
+import mdx from './page_template.mdx';
+import { KibanaPageTemplateSolutionNavProps } from './solution_nav';
+import { KibanaPageTemplateProps } from './types';
+
+export default {
+ title: 'Page Template/Page Template',
+ description:
+ 'A thin wrapper around `EuiTemplate`. Takes care of styling, empty state and no data config',
+ parameters: {
+ docs: {
+ page: mdx,
+ },
+ },
+};
+
+type Params = Pick;
+
+const noDataConfig = {
+ solution: 'Kibana',
+ action: {
+ elasticAgent: {},
+ },
+ docsLink: 'http://wwww.docs.elastic.co',
+};
+
+const items: KibanaPageTemplateSolutionNavProps['items'] = [
+ {
+ name: 'Ingest',
+ id: '1',
+ items: [
+ {
+ name: 'Ingest Node Pipelines',
+ id: '1.1',
+ },
+ {
+ name: 'Logstash Pipelines',
+ id: '1.2',
+ },
+ {
+ name: 'Beats Central Management',
+ id: '1.3',
+ },
+ ],
+ },
+ {
+ name: 'Data',
+ id: '2',
+ items: [
+ {
+ name: 'Index Management',
+ id: '2.1',
+ },
+ {
+ name: 'Index Lifecycle Policies',
+ id: '2.2',
+ },
+ {
+ name: 'Snapshot and Restore',
+ id: '2.3',
+ },
+ ],
+ },
+];
+
+const solutionNavBar = {
+ items,
+ logo: 'logoKibana',
+ name: 'Kibana',
+ action: { elasticAgent: {} },
+};
+
+const content = (
+
+
+ Page Content goes here
+
+
+);
+
+const header = {
+ iconType: 'logoKibana',
+ pageTitle: 'Kibana',
+ description: 'Welcome to Kibana!',
+ rightSideItems: [Add something, Do something],
+};
+
+export const WithNoDataConfig = () => {
+ return ;
+};
+
+export const WithNoDataConfigAndSolutionNav = () => {
+ return ;
+};
+
+export const PureComponent = (params: Params) => {
+ return (
+
+ {content}
+
+ );
+};
+
+PureComponent.argTypes = {
+ isEmptyState: {
+ control: 'boolean',
+ defaultValue: false,
+ },
+ pageHeader: {
+ control: 'boolean',
+ defaultValue: true,
+ },
+ solutionNav: {
+ control: 'boolean',
+ defaultValue: true,
+ },
+};
+
+PureComponent.parameters = {
+ layout: 'fullscreen',
+};
+
+WithNoDataConfig.parameters = {
+ layout: 'fullscreen',
+};
+
+WithNoDataConfigAndSolutionNav.parameters = {
+ layout: 'fullscreen',
+};
diff --git a/packages/kbn-shared-ux-components/src/page_template/page_template.test.tsx b/packages/kbn-shared-ux-components/src/page_template/page_template.test.tsx
new file mode 100644
index 0000000000000..8d073e14f7776
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/page_template.test.tsx
@@ -0,0 +1,113 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React from 'react';
+import { shallow, render } from 'enzyme';
+import { KibanaPageTemplate } from './page_template';
+import { KibanaPageTemplateSolutionNavProps } from './solution_nav';
+import { NoDataPageProps } from './no_data_page';
+
+const items: KibanaPageTemplateSolutionNavProps['items'] = [
+ {
+ name: 'Ingest',
+ id: '1',
+ items: [
+ {
+ name: 'Ingest Node Pipelines',
+ id: '1.1',
+ },
+ {
+ name: 'Logstash Pipelines',
+ id: '1.2',
+ },
+ {
+ name: 'Beats Central Management',
+ id: '1.3',
+ },
+ ],
+ },
+ {
+ name: 'Data',
+ id: '2',
+ items: [
+ {
+ name: 'Index Management',
+ id: '2.1',
+ },
+ {
+ name: 'Index Lifecycle Policies',
+ id: '2.2',
+ },
+ {
+ name: 'Snapshot and Restore',
+ id: '2.3',
+ },
+ ],
+ },
+];
+
+const solutionNav = {
+ name: 'Kibana',
+ icon: 'logoKibana',
+ items,
+};
+
+const noDataConfig: NoDataPageProps = {
+ solution: 'Elastic',
+ action: {
+ elasticAgent: {},
+ },
+ docsLink: 'test',
+};
+
+describe('KibanaPageTemplate', () => {
+ test('render noDataConfig && solutionNav', () => {
+ const component = shallow(
+
+ );
+ expect(component).toMatchSnapshot();
+ });
+
+ test('render noDataConfig', () => {
+ const component = shallow();
+ expect(component).toMatchSnapshot();
+ });
+
+ test('render solutionNav', () => {
+ const component = shallow(
+
+ Child element
+
+ );
+ expect(component).toMatchSnapshot();
+ });
+
+ test('render basic template', () => {
+ const component = render(
+
+ Child element
+
+ );
+ expect(component).toMatchSnapshot();
+ });
+});
diff --git a/packages/kbn-shared-ux-components/src/page_template/page_template.tsx b/packages/kbn-shared-ux-components/src/page_template/page_template.tsx
new file mode 100644
index 0000000000000..6d63d54e9b9dd
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/page_template.tsx
@@ -0,0 +1,69 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import './page_template.scss';
+
+import React, { FunctionComponent } from 'react';
+
+import { NoDataConfigPage, NoDataConfigPageWithSolutionNavBar } from './no_data_page';
+import { KibanaPageTemplateInner, KibanaPageTemplateWithSolutionNav } from './page_template_inner';
+import { KibanaPageTemplateProps } from './types';
+
+export const KibanaPageTemplate: FunctionComponent = ({
+ template,
+ className,
+ children,
+ solutionNav,
+ noDataConfig,
+ ...rest
+}) => {
+ /**
+ * If passing the custom template of `noDataConfig`
+ */
+ if (noDataConfig && solutionNav) {
+ return (
+
+ );
+ }
+
+ if (noDataConfig) {
+ return (
+
+ );
+ }
+
+ if (solutionNav) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+};
diff --git a/packages/kbn-shared-ux-components/src/page_template/page_template_inner.test.tsx b/packages/kbn-shared-ux-components/src/page_template/page_template_inner.test.tsx
new file mode 100644
index 0000000000000..c17b83c4f4eed
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/page_template_inner.test.tsx
@@ -0,0 +1,67 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+// imports from npm packages
+import React from 'react';
+import { shallow } from 'enzyme';
+
+// imports from elastic packages
+import { EuiEmptyPrompt, EuiPageTemplate } from '@elastic/eui';
+
+// imports from immediate files
+import { KibanaPageTemplateInner } from './page_template_inner';
+
+describe('KibanaPageTemplateInner', () => {
+ const pageHeader = {
+ iconType: 'test',
+ pageTitle: 'test',
+ description: 'test',
+ rightSideItems: ['test'],
+ };
+
+ describe('isEmpty', () => {
+ test('pageHeader & children', () => {
+ const component = shallow(
+ Child element}
+ />
+ );
+ expect(component).toMatchSnapshot();
+ expect(component.find('[data-test-subj="child"]').length).toBe(1);
+ });
+
+ test('pageHeader & no children', () => {
+ const component = shallow(
+
+ );
+ expect(component).toMatchSnapshot();
+ expect(component.find(EuiEmptyPrompt).length).toBe(1);
+ });
+
+ test('no pageHeader', () => {
+ const component = shallow(
+
+ );
+ expect(component).toMatchSnapshot();
+ });
+ });
+
+ test('custom template', () => {
+ const component = shallow(
+
+ );
+ expect(component).toMatchSnapshot();
+ expect(component.find(EuiPageTemplate).props().template).toEqual('centeredContent');
+ });
+});
diff --git a/packages/kbn-shared-ux-components/src/page_template/page_template_inner.tsx b/packages/kbn-shared-ux-components/src/page_template/page_template_inner.tsx
new file mode 100644
index 0000000000000..cef22f2713efc
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/page_template_inner.tsx
@@ -0,0 +1,67 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React, { FunctionComponent } from 'react';
+
+import { EuiEmptyPrompt, EuiPageTemplate } from '@elastic/eui';
+
+import { withSolutionNav } from './with_solution_nav';
+import { KibanaPageTemplateProps } from './types';
+import { getClasses } from './util';
+
+type Props = KibanaPageTemplateProps;
+
+/**
+ * A thin wrapper around EuiPageTemplate with a few Kibana specific additions
+ */
+export const KibanaPageTemplateInner: FunctionComponent = ({
+ template,
+ className,
+ pageHeader,
+ children,
+ isEmptyState,
+ ...rest
+}) => {
+ /**
+ * An easy way to create the right content for empty pages
+ */
+ const emptyStateDefaultTemplate = 'centeredBody';
+ let header = pageHeader;
+
+ if (isEmptyState) {
+ if (pageHeader && !children) {
+ template = template ?? emptyStateDefaultTemplate;
+ const { iconType, pageTitle, description, rightSideItems } = pageHeader;
+ const title = pageTitle ? {pageTitle}
: undefined;
+ const body = description ? {description}
: undefined;
+ header = undefined;
+ children = (
+
+ );
+ } else if (pageHeader && children) {
+ template = template ?? 'centeredContent';
+ } else if (!pageHeader) {
+ template = template ?? emptyStateDefaultTemplate;
+ }
+ }
+
+ const classes = getClasses(template, className);
+ return (
+
+ {children}
+
+ );
+};
+
+export const KibanaPageTemplateWithSolutionNav = withSolutionNav(KibanaPageTemplateInner);
diff --git a/packages/kbn-shared-ux-components/src/page_template/types.ts b/packages/kbn-shared-ux-components/src/page_template/types.ts
new file mode 100644
index 0000000000000..cd4764a976db8
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/types.ts
@@ -0,0 +1,30 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { EuiPageTemplateProps } from '@elastic/eui';
+import { KibanaPageTemplateSolutionNavProps } from './solution_nav';
+import { NoDataPageProps } from './no_data_page';
+
+export type KibanaPageTemplateProps = EuiPageTemplateProps & {
+ /**
+ * Changes the template type depending on other props provided.
+ * With `pageHeader` only: Uses `centeredBody` and fills an EuiEmptyPrompt with `pageHeader` info.
+ * With `children` only: Uses `centeredBody`
+ * With `pageHeader` and `children`: Uses `centeredContent`
+ */
+ isEmptyState?: boolean;
+ /**
+ * Quick creation of EuiSideNav. Hooks up mobile instance too
+ */
+ solutionNav?: KibanaPageTemplateSolutionNavProps;
+ /**
+ * Accepts a configuration object, that when provided, ignores pageHeader and children and instead
+ * displays Agent, Beats, and custom cards to direct users to the right ingest location
+ */
+ noDataConfig?: NoDataPageProps;
+};
diff --git a/packages/kbn-shared-ux-components/src/page_template/util/constants.ts b/packages/kbn-shared-ux-components/src/page_template/util/constants.ts
new file mode 100644
index 0000000000000..92dbe1cb16279
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/util/constants.ts
@@ -0,0 +1,21 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { KibanaPageTemplateProps } from '../types';
+
+export const NO_DATA_PAGE_MAX_WIDTH = 950;
+
+export const NO_DATA_PAGE_TEMPLATE_PROPS: KibanaPageTemplateProps = {
+ restrictWidth: NO_DATA_PAGE_MAX_WIDTH,
+ template: 'centeredBody',
+ pageContentProps: {
+ hasShadow: false,
+ color: 'transparent',
+ paddingSize: 'none',
+ },
+};
diff --git a/packages/kbn-shared-ux-components/src/page_template/util/index.ts b/packages/kbn-shared-ux-components/src/page_template/util/index.ts
new file mode 100644
index 0000000000000..adfefdf834566
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/util/index.ts
@@ -0,0 +1,10 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+export { getClasses } from './presentation';
+export * from './constants';
diff --git a/packages/kbn-shared-ux-components/src/page_template/util/presentation.ts b/packages/kbn-shared-ux-components/src/page_template/util/presentation.ts
new file mode 100644
index 0000000000000..ab7144ee37b57
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/util/presentation.ts
@@ -0,0 +1,13 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import classNames from 'classnames';
+
+export const getClasses = (template: string | undefined, className: string | undefined) => {
+ return classNames('kbnPageTemplate', { [`kbnPageTemplate--${template}`]: template }, className);
+};
diff --git a/packages/kbn-shared-ux-components/src/page_template/with_solution_nav.test.tsx b/packages/kbn-shared-ux-components/src/page_template/with_solution_nav.test.tsx
new file mode 100644
index 0000000000000..0d0ac4cf71bfc
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/with_solution_nav.test.tsx
@@ -0,0 +1,80 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { shallow } from 'enzyme';
+import React from 'react';
+import { withSolutionNav } from './with_solution_nav';
+import { KibanaPageTemplateSolutionNavProps } from './solution_nav';
+
+const TestComponent = () => {
+ return This is a wrapped component
;
+};
+
+const items: KibanaPageTemplateSolutionNavProps['items'] = [
+ {
+ name: 'Ingest',
+ id: '1',
+ items: [
+ {
+ name: 'Ingest Node Pipelines',
+ id: '1.1',
+ },
+ {
+ name: 'Logstash Pipelines',
+ id: '1.2',
+ },
+ {
+ name: 'Beats Central Management',
+ id: '1.3',
+ },
+ ],
+ },
+ {
+ name: 'Data',
+ id: '2',
+ items: [
+ {
+ name: 'Index Management',
+ id: '2.1',
+ },
+ {
+ name: 'Index Lifecycle Policies',
+ id: '2.2',
+ },
+ {
+ name: 'Snapshot and Restore',
+ id: '2.3',
+ },
+ ],
+ },
+];
+
+const solutionNav = {
+ name: 'Kibana',
+ icon: 'logoKibana',
+ items,
+};
+
+describe('WithSolutionNav', () => {
+ test('renders wrapped component', () => {
+ const WithSolutionNavTestComponent = withSolutionNav(TestComponent);
+ const component = shallow();
+ expect(component).toMatchSnapshot();
+ });
+
+ test('with children', () => {
+ const WithSolutionNavTestComponent = withSolutionNav(TestComponent);
+ const component = shallow(
+
+ Child component
+
+ );
+ expect(component).toMatchSnapshot();
+ expect(component.find('.child').html()).toContain('Child component');
+ });
+});
diff --git a/packages/kbn-shared-ux-components/src/page_template/with_solution_nav.tsx b/packages/kbn-shared-ux-components/src/page_template/with_solution_nav.tsx
new file mode 100644
index 0000000000000..07d78dc87f40b
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/with_solution_nav.tsx
@@ -0,0 +1,76 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React, { ComponentType, useState } from 'react';
+import classNames from 'classnames';
+import { useIsWithinBreakpoints } from '@elastic/eui';
+import { EuiPageSideBarProps } from '@elastic/eui/src/components/page/page_side_bar';
+import { KibanaPageTemplateSolutionNav, KibanaPageTemplateSolutionNavProps } from './solution_nav';
+import { KibanaPageTemplateProps } from './types';
+
+// https://reactjs.org/docs/higher-order-components.html#convention-wrap-the-display-name-for-easy-debugging
+function getDisplayName(Component: ComponentType) {
+ return Component.displayName || Component.name || 'UnnamedComponent';
+}
+
+type SolutionNavProps = KibanaPageTemplateProps & {
+ solutionNav: KibanaPageTemplateSolutionNavProps;
+};
+
+const SOLUTION_NAV_COLLAPSED_KEY = 'solutionNavIsCollapsed';
+
+export const withSolutionNav = (WrappedComponent: ComponentType) => {
+ const WithSolutionNav = (props: SolutionNavProps) => {
+ const isMediumBreakpoint = useIsWithinBreakpoints(['m']);
+ const isLargerBreakpoint = useIsWithinBreakpoints(['l', 'xl']);
+ const [isSideNavOpenOnDesktop, setisSideNavOpenOnDesktop] = useState(
+ !JSON.parse(String(localStorage.getItem(SOLUTION_NAV_COLLAPSED_KEY)))
+ );
+ const { solutionNav, ...propagatedProps } = props;
+ const { children, isEmptyState, template } = propagatedProps;
+ const toggleOpenOnDesktop = () => {
+ setisSideNavOpenOnDesktop(!isSideNavOpenOnDesktop);
+ // Have to store it as the opposite of the default we want
+ localStorage.setItem(SOLUTION_NAV_COLLAPSED_KEY, JSON.stringify(isSideNavOpenOnDesktop));
+ };
+ const sideBarClasses = classNames(
+ 'kbnPageTemplate__pageSideBar',
+ {
+ 'kbnPageTemplate__pageSideBar--shrink':
+ isMediumBreakpoint || (isLargerBreakpoint && !isSideNavOpenOnDesktop),
+ },
+ props.pageSideBarProps?.className
+ );
+
+ const templateToUse = isEmptyState && !template ? 'centeredContent' : template;
+
+ const pageSideBar = (
+
+ );
+ const pageSideBarProps = {
+ paddingSize: 'none',
+ ...props.pageSideBarProps,
+ className: sideBarClasses,
+ } as EuiPageSideBarProps; // needed because for some reason 'none' is not recognized as a valid value for paddingSize
+ return (
+
+ {children}
+
+ );
+ };
+
+ WithSolutionNav.displayName = `WithSolutionNavBar(${getDisplayName(WrappedComponent)})`;
+
+ return WithSolutionNav;
+};
From f20218f57078c38e7245a64b9edc5d5dea69ab7f Mon Sep 17 00:00:00 2001
From: Kevin Logan <56395104+kevinlog@users.noreply.github.com>
Date: Mon, 11 Apr 2022 11:59:38 -0700
Subject: [PATCH 14/75] [Security Solution] Fix Endpoint count in policy list,
text updates (#129907)
---
.../management/pages/policy/view/policy_list.tsx | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx
index 44649936c490a..bdc0c7d779b15 100644
--- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx
@@ -89,7 +89,11 @@ export const PolicyList = memo(() => {
const policyIdToEndpointCount = useMemo(() => {
const map = new Map();
for (const policy of endpointCount?.items) {
- map.set(policy.package_policies[0], policy.agents ?? 0);
+ for (const packagePolicyId of policy.package_policies) {
+ if (policyIds.includes(packagePolicyId as string)) {
+ map.set(packagePolicyId, policy.agents ?? 0);
+ }
+ }
}
// error with the endpointCount api call, set default count to 0
@@ -289,11 +293,11 @@ export const PolicyList = memo(() => {
data-test-subj="policyListPage"
hideHeader={totalItemCount === 0}
title={i18n.translate('xpack.securitySolution.policy.list.title', {
- defaultMessage: 'Policy List',
+ defaultMessage: 'Policies',
})}
subtitle={i18n.translate('xpack.securitySolution.policy.list.subtitle', {
defaultMessage:
- 'Use endpoint policies to customize endpoint security protections and other configurations',
+ 'Use policies to customize endpoint and cloud workload protections and other configurations',
})}
>
{totalItemCount > 0 ? (
From 6954b0ff6b51a220498ac7926fad9751731cdea7 Mon Sep 17 00:00:00 2001
From: Andrew Tate
Date: Mon, 11 Apr 2022 14:09:02 -0500
Subject: [PATCH 15/75] [Discover] make field icons consistent across field
list and doc tables (#129621)
---
.../components/sidebar/discover_field.tsx | 8 ++--
.../doc_viewer_table/legacy/table.tsx | 7 +++-
.../components/doc_viewer_table/table.tsx | 7 +++-
.../utils/get_type_for_field_icon.test.ts | 39 +++++++++++++++++++
.../public/utils/get_type_for_field_icon.ts | 17 ++++++++
5 files changed, 73 insertions(+), 5 deletions(-)
create mode 100644 src/plugins/discover/public/utils/get_type_for_field_icon.test.ts
create mode 100644 src/plugins/discover/public/utils/get_type_for_field_icon.ts
diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx
index e629c85c6d242..e14d9f7a0e5a7 100644
--- a/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx
+++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx
@@ -25,6 +25,7 @@ import { i18n } from '@kbn/i18n';
import { UiCounterMetricType } from '@kbn/analytics';
import classNames from 'classnames';
import { FieldButton, FieldIcon } from '@kbn/react-field';
+import { getTypeForFieldIcon } from '../../../../utils/get_type_for_field_icon';
import { DiscoverFieldDetails } from './discover_field_details';
import { FieldDetails } from './types';
import type { DataViewField, DataView } from '../../../../../../data_views/public';
@@ -59,9 +60,10 @@ const FieldInfoIcon: React.FC = memo(() => (
));
const DiscoverFieldTypeIcon: React.FC<{ field: DataViewField }> = memo(({ field }) => {
- // If it's a string type, we want to distinguish between keyword and text
- const tempType = field.type === 'string' && field.esTypes ? field.esTypes[0] : field.type;
- return ;
+ const typeForIcon = getTypeForFieldIcon(field);
+ return (
+
+ );
});
const FieldName: React.FC<{ field: DataViewField }> = memo(({ field }) => {
diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table.tsx
index aab4856d6698c..aa44f0d56889c 100644
--- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table.tsx
+++ b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table.tsx
@@ -9,6 +9,7 @@
import '../table.scss';
import React, { useCallback, useMemo } from 'react';
import { EuiInMemoryTable } from '@elastic/eui';
+import { getTypeForFieldIcon } from '../../../../../utils/get_type_for_field_icon';
import { useDiscoverServices } from '../../../../../utils/use_discover_services';
import { flattenHit } from '../../../../../../../data/public';
import { SHOW_MULTIFIELDS } from '../../../../../../common';
@@ -73,7 +74,11 @@ export const DocViewerLegacyTable = ({
.map((field) => {
const fieldMapping = mapping(field);
const displayName = fieldMapping?.displayName ?? field;
- const fieldType = isNestedFieldParent(field, dataView) ? 'nested' : fieldMapping?.type;
+ const fieldType = isNestedFieldParent(field, dataView)
+ ? 'nested'
+ : fieldMapping
+ ? getTypeForFieldIcon(fieldMapping)
+ : undefined;
const ignored = getIgnoredReason(fieldMapping ?? field, hit._ignored);
return {
action: {
diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.tsx
index 7aa372e36adff..4742dd3d8f585 100644
--- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.tsx
+++ b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.tsx
@@ -27,6 +27,7 @@ import {
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { debounce } from 'lodash';
+import { getTypeForFieldIcon } from '../../../../utils/get_type_for_field_icon';
import { useDiscoverServices } from '../../../../utils/use_discover_services';
import { Storage } from '../../../../../../kibana_utils/public';
import { usePager } from '../../../../utils/use_pager';
@@ -157,7 +158,11 @@ export const DocViewerTable = ({
(field: string) => {
const fieldMapping = mapping(field);
const displayName = fieldMapping?.displayName ?? field;
- const fieldType = isNestedFieldParent(field, dataView) ? 'nested' : fieldMapping?.type;
+ const fieldType = isNestedFieldParent(field, dataView)
+ ? 'nested'
+ : fieldMapping
+ ? getTypeForFieldIcon(fieldMapping)
+ : undefined;
const ignored = getIgnoredReason(fieldMapping ?? field, hit._ignored);
diff --git a/src/plugins/discover/public/utils/get_type_for_field_icon.test.ts b/src/plugins/discover/public/utils/get_type_for_field_icon.test.ts
new file mode 100644
index 0000000000000..bffa0fecaed74
--- /dev/null
+++ b/src/plugins/discover/public/utils/get_type_for_field_icon.test.ts
@@ -0,0 +1,39 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { DataViewField } from 'src/plugins/data_views/common';
+import { getTypeForFieldIcon } from './get_type_for_field_icon';
+
+describe('getTypeForFieldIcon', () => {
+ it('extracts type for non-string types', () => {
+ expect(
+ getTypeForFieldIcon({
+ type: 'not-string',
+ esTypes: ['bar'],
+ } as DataViewField)
+ ).toBe('not-string');
+ });
+
+ it('extracts type when type is string but esTypes is unavailable', () => {
+ expect(
+ getTypeForFieldIcon({
+ type: 'string',
+ esTypes: undefined,
+ } as DataViewField)
+ ).toBe('string');
+ });
+
+ it('extracts esType when type is string and esTypes is available', () => {
+ expect(
+ getTypeForFieldIcon({
+ type: 'string',
+ esTypes: ['version'],
+ } as DataViewField)
+ ).toBe('version');
+ });
+});
diff --git a/src/plugins/discover/public/utils/get_type_for_field_icon.ts b/src/plugins/discover/public/utils/get_type_for_field_icon.ts
new file mode 100644
index 0000000000000..bb3f65ed3e01c
--- /dev/null
+++ b/src/plugins/discover/public/utils/get_type_for_field_icon.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { DataViewField } from 'src/plugins/data_views/common';
+
+/**
+ * Extracts the type from a data view field that will match the right icon.
+ *
+ * We define custom logic for Discover in order to distinguish between various "string" types.
+ */
+export const getTypeForFieldIcon = (field: DataViewField) =>
+ field.type === 'string' && field.esTypes ? field.esTypes[0] : field.type;
From 837813eef89913e422f9c2b0a7b3859fa2ff5c51 Mon Sep 17 00:00:00 2001
From: Chris Cowan
Date: Mon, 11 Apr 2022 13:09:36 -0600
Subject: [PATCH 16/75] [Logs UI][Rules] Add integration tests for Log
Threshold Rule (#128019)
* [Logs UI][Rules] Add integration tests for Log Threshold Rule
* Fixing tests
* Add timestamp to preview calls
* Update test to reflect new argument count
---
.../log_threshold_chart_preview.ts | 23 +-
.../log_threshold_executor.test.ts | 16 +-
.../log_threshold/log_threshold_executor.ts | 73 ++++--
.../api_integration/apis/logs_ui/index.ts | 1 +
.../apis/logs_ui/log_threshold_alert.ts | 236 ++++++++++++++++++
5 files changed, 321 insertions(+), 28 deletions(-)
create mode 100644 x-pack/test/api_integration/apis/logs_ui/log_threshold_alert.ts
diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_chart_preview.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_chart_preview.ts
index 56bbd69240dc2..4483ad30c0246 100644
--- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_chart_preview.ts
+++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_chart_preview.ts
@@ -47,11 +47,28 @@ export async function getChartPreviewData(
timeSize: timeSize * buckets,
};
- const { rangeFilter } = buildFiltersFromCriteria(expandedAlertParams, timestampField);
+ const executionTimestamp = Date.now();
+ const { rangeFilter } = buildFiltersFromCriteria(
+ expandedAlertParams,
+ timestampField,
+ executionTimestamp
+ );
const query = isGrouped
- ? getGroupedESQuery(expandedAlertParams, timestampField, indices, runtimeMappings)
- : getUngroupedESQuery(expandedAlertParams, timestampField, indices, runtimeMappings);
+ ? getGroupedESQuery(
+ expandedAlertParams,
+ timestampField,
+ indices,
+ runtimeMappings,
+ executionTimestamp
+ )
+ : getUngroupedESQuery(
+ expandedAlertParams,
+ timestampField,
+ indices,
+ runtimeMappings,
+ executionTimestamp
+ );
if (!query) {
throw new Error('ES query could not be built from the provided alert params');
diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts
index d6b599336fac8..78934d09755be 100644
--- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts
+++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts
@@ -134,6 +134,7 @@ const baseRuleParams: Pick = {
const TIMESTAMP_FIELD = '@timestamp';
const FILEBEAT_INDEX = 'filebeat-*';
+const EXECUTION_TIMESTAMP = new Date('2022-01-01T00:00:00.000Z').valueOf();
const runtimeMappings: estypes.MappingRuntimeFields = {
runtime_field: {
@@ -166,7 +167,7 @@ describe('Log threshold executor', () => {
...baseRuleParams,
criteria: positiveCriteria,
};
- const filters = buildFiltersFromCriteria(ruleParams, TIMESTAMP_FIELD);
+ const filters = buildFiltersFromCriteria(ruleParams, TIMESTAMP_FIELD, EXECUTION_TIMESTAMP);
expect(filters.mustFilters).toEqual(expectedPositiveFilterClauses);
});
@@ -175,14 +176,14 @@ describe('Log threshold executor', () => {
...baseRuleParams,
criteria: negativeCriteria,
};
- const filters = buildFiltersFromCriteria(ruleParams, TIMESTAMP_FIELD);
+ const filters = buildFiltersFromCriteria(ruleParams, TIMESTAMP_FIELD, EXECUTION_TIMESTAMP);
expect(filters.mustNotFilters).toEqual(expectedNegativeFilterClauses);
});
test('Handles time range', () => {
const ruleParams: RuleParams = { ...baseRuleParams, criteria: [] };
- const filters = buildFiltersFromCriteria(ruleParams, TIMESTAMP_FIELD);
+ const filters = buildFiltersFromCriteria(ruleParams, TIMESTAMP_FIELD, EXECUTION_TIMESTAMP);
expect(typeof filters.rangeFilter.range[TIMESTAMP_FIELD].gte).toBe('number');
expect(typeof filters.rangeFilter.range[TIMESTAMP_FIELD].lte).toBe('number');
expect(filters.rangeFilter.range[TIMESTAMP_FIELD].format).toBe('epoch_millis');
@@ -204,7 +205,8 @@ describe('Log threshold executor', () => {
ruleParams,
TIMESTAMP_FIELD,
FILEBEAT_INDEX,
- runtimeMappings
+ runtimeMappings,
+ EXECUTION_TIMESTAMP
);
expect(query).toEqual({
index: 'filebeat-*',
@@ -254,7 +256,8 @@ describe('Log threshold executor', () => {
ruleParams,
TIMESTAMP_FIELD,
FILEBEAT_INDEX,
- runtimeMappings
+ runtimeMappings,
+ EXECUTION_TIMESTAMP
);
expect(query).toEqual({
@@ -324,7 +327,8 @@ describe('Log threshold executor', () => {
ruleParams,
TIMESTAMP_FIELD,
FILEBEAT_INDEX,
- runtimeMappings
+ runtimeMappings,
+ EXECUTION_TIMESTAMP
);
expect(query).toEqual({
diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts
index be106226d0ee4..12b523d126f80 100644
--- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts
+++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts
@@ -118,7 +118,7 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) =>
: relativeViewInAppUrl;
const sharedContext = {
- timestamp: new Date().toISOString(),
+ timestamp: startedAt.toISOString(),
viewInAppUrl,
};
actions.forEach((actionSet) => {
@@ -149,7 +149,8 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) =>
indices,
runtimeMappings,
scopedClusterClient.asCurrentUser,
- alertFactory
+ alertFactory,
+ startedAt.valueOf()
);
} else {
await executeRatioAlert(
@@ -158,7 +159,8 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) =>
indices,
runtimeMappings,
scopedClusterClient.asCurrentUser,
- alertFactory
+ alertFactory,
+ startedAt.valueOf()
);
}
} catch (e) {
@@ -166,15 +168,22 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) =>
}
});
-async function executeAlert(
+export async function executeAlert(
ruleParams: CountRuleParams,
timestampField: string,
indexPattern: string,
runtimeMappings: estypes.MappingRuntimeFields,
esClient: ElasticsearchClient,
- alertFactory: LogThresholdAlertFactory
+ alertFactory: LogThresholdAlertFactory,
+ executionTimestamp: number
) {
- const query = getESQuery(ruleParams, timestampField, indexPattern, runtimeMappings);
+ const query = getESQuery(
+ ruleParams,
+ timestampField,
+ indexPattern,
+ runtimeMappings,
+ executionTimestamp
+ );
if (!query) {
throw new Error('ES query could not be built from the provided alert params');
@@ -187,13 +196,14 @@ async function executeAlert(
}
}
-async function executeRatioAlert(
+export async function executeRatioAlert(
ruleParams: RatioRuleParams,
timestampField: string,
indexPattern: string,
runtimeMappings: estypes.MappingRuntimeFields,
esClient: ElasticsearchClient,
- alertFactory: LogThresholdAlertFactory
+ alertFactory: LogThresholdAlertFactory,
+ executionTimestamp: number
) {
// Ratio alert params are separated out into two standard sets of alert params
const numeratorParams: RuleParams = {
@@ -206,12 +216,19 @@ async function executeRatioAlert(
criteria: getDenominator(ruleParams.criteria),
};
- const numeratorQuery = getESQuery(numeratorParams, timestampField, indexPattern, runtimeMappings);
+ const numeratorQuery = getESQuery(
+ numeratorParams,
+ timestampField,
+ indexPattern,
+ runtimeMappings,
+ executionTimestamp
+ );
const denominatorQuery = getESQuery(
denominatorParams,
timestampField,
indexPattern,
- runtimeMappings
+ runtimeMappings,
+ executionTimestamp
);
if (!numeratorQuery || !denominatorQuery) {
@@ -247,11 +264,24 @@ const getESQuery = (
alertParams: Omit & { criteria: CountCriteria },
timestampField: string,
indexPattern: string,
- runtimeMappings: estypes.MappingRuntimeFields
+ runtimeMappings: estypes.MappingRuntimeFields,
+ executionTimestamp: number
) => {
return hasGroupBy(alertParams)
- ? getGroupedESQuery(alertParams, timestampField, indexPattern, runtimeMappings)
- : getUngroupedESQuery(alertParams, timestampField, indexPattern, runtimeMappings);
+ ? getGroupedESQuery(
+ alertParams,
+ timestampField,
+ indexPattern,
+ runtimeMappings,
+ executionTimestamp
+ )
+ : getUngroupedESQuery(
+ alertParams,
+ timestampField,
+ indexPattern,
+ runtimeMappings,
+ executionTimestamp
+ );
};
export const processUngroupedResults = (
@@ -452,13 +482,14 @@ export const processGroupByRatioResults = (
export const buildFiltersFromCriteria = (
params: Pick & { criteria: CountCriteria },
- timestampField: string
+ timestampField: string,
+ executionTimestamp: number
) => {
const { timeSize, timeUnit, criteria } = params;
const interval = `${timeSize}${timeUnit}`;
const intervalAsSeconds = getIntervalInSeconds(interval);
const intervalAsMs = intervalAsSeconds * 1000;
- const to = Date.now();
+ const to = executionTimestamp;
const from = to - intervalAsMs;
const positiveComparators = getPositiveComparators();
@@ -511,7 +542,8 @@ export const getGroupedESQuery = (
},
timestampField: string,
index: string,
- runtimeMappings: estypes.MappingRuntimeFields
+ runtimeMappings: estypes.MappingRuntimeFields,
+ executionTimestamp: number
): estypes.SearchRequest | undefined => {
// IMPORTANT:
// For the group by scenario we need to account for users utilizing "less than" configurations
@@ -532,7 +564,8 @@ export const getGroupedESQuery = (
const { rangeFilter, groupedRangeFilter, mustFilters, mustNotFilters } = buildFiltersFromCriteria(
params,
- timestampField
+ timestampField,
+ executionTimestamp
);
if (isOptimizableGroupedThreshold(comparator, value)) {
@@ -616,11 +649,13 @@ export const getUngroupedESQuery = (
params: Pick & { criteria: CountCriteria },
timestampField: string,
index: string,
- runtimeMappings: estypes.MappingRuntimeFields
+ runtimeMappings: estypes.MappingRuntimeFields,
+ executionTimestamp: number
): object => {
const { rangeFilter, mustFilters, mustNotFilters } = buildFiltersFromCriteria(
params,
- timestampField
+ timestampField,
+ executionTimestamp
);
const body: estypes.SearchRequest['body'] = {
diff --git a/x-pack/test/api_integration/apis/logs_ui/index.ts b/x-pack/test/api_integration/apis/logs_ui/index.ts
index 125ca65f52734..625ff24ce25cd 100644
--- a/x-pack/test/api_integration/apis/logs_ui/index.ts
+++ b/x-pack/test/api_integration/apis/logs_ui/index.ts
@@ -10,5 +10,6 @@ import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('Logs UI routes', () => {
loadTestFile(require.resolve('./log_views'));
+ loadTestFile(require.resolve('./log_threshold_alert'));
});
}
diff --git a/x-pack/test/api_integration/apis/logs_ui/log_threshold_alert.ts b/x-pack/test/api_integration/apis/logs_ui/log_threshold_alert.ts
new file mode 100644
index 0000000000000..18f3a181dde53
--- /dev/null
+++ b/x-pack/test/api_integration/apis/logs_ui/log_threshold_alert.ts
@@ -0,0 +1,236 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import expect from '@kbn/expect';
+import sinon from 'sinon';
+import {
+ executeAlert,
+ executeRatioAlert,
+} from '../../../../plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor';
+import { DATES } from '../metrics_ui/constants';
+import { FtrProviderContext } from '../../ftr_provider_context';
+import {
+ Comparator,
+ TimeUnit,
+ RatioCriteria,
+} from '../../../../plugins/infra/common/alerting/logs/log_threshold/types';
+
+export default function ({ getService }: FtrProviderContext) {
+ const esArchiver = getService('esArchiver');
+ const esClient = getService('es');
+ describe('Log Threshold Rule', () => {
+ describe('executeAlert', () => {
+ before(() => esArchiver.load('x-pack/test/functional/es_archives/infra/alerts_test_data'));
+ after(() => esArchiver.unload('x-pack/test/functional/es_archives/infra/alerts_test_data'));
+
+ describe('without group by', () => {
+ it('should work', async () => {
+ const timestamp = new Date(DATES['alert-test-data'].gauge.max);
+ const alertFactory = sinon.fake();
+ const ruleParams = {
+ count: {
+ comparator: Comparator.GT_OR_EQ,
+ value: 1,
+ },
+ timeUnit: 'm' as TimeUnit,
+ timeSize: 5,
+ criteria: [
+ {
+ field: 'env',
+ comparator: Comparator.NOT_EQ,
+ value: 'dev',
+ },
+ ],
+ };
+ await executeAlert(
+ ruleParams,
+ '@timestamp',
+ 'alerts-test-data',
+ {},
+ esClient,
+ alertFactory,
+ timestamp.valueOf()
+ );
+ expect(alertFactory.callCount).to.equal(1);
+ expect(alertFactory.getCall(0).args).to.eql([
+ '*',
+ '2 log entries in the last 5 mins. Alert when ≥ 1.',
+ 2,
+ 1,
+ [
+ {
+ actionGroup: 'logs.threshold.fired',
+ context: {
+ conditions: 'env does not equal dev',
+ group: null,
+ isRatio: false,
+ matchingDocuments: 2,
+ reason: '2 log entries in the last 5 mins. Alert when ≥ 1.',
+ },
+ },
+ ],
+ ]);
+ });
+ });
+
+ describe('with group by', () => {
+ it('should work', async () => {
+ const timestamp = new Date(DATES['alert-test-data'].gauge.max);
+ const alertFactory = sinon.fake();
+ const ruleParams = {
+ count: {
+ comparator: Comparator.GT_OR_EQ,
+ value: 1,
+ },
+ timeUnit: 'm' as TimeUnit,
+ timeSize: 5,
+ groupBy: ['env'],
+ criteria: [
+ {
+ field: 'env',
+ comparator: Comparator.NOT_EQ,
+ value: 'test',
+ },
+ ],
+ };
+ await executeAlert(
+ ruleParams,
+ '@timestamp',
+ 'alerts-test-data',
+ {},
+ esClient,
+ alertFactory,
+ timestamp.valueOf()
+ );
+ expect(alertFactory.callCount).to.equal(2);
+ expect(alertFactory.getCall(0).args).to.eql([
+ 'dev',
+ '2 log entries in the last 5 mins for dev. Alert when ≥ 1.',
+ 2,
+ 1,
+ [
+ {
+ actionGroup: 'logs.threshold.fired',
+ context: {
+ conditions: 'env does not equal test',
+ group: 'dev',
+ isRatio: false,
+ matchingDocuments: 2,
+ reason: '2 log entries in the last 5 mins for dev. Alert when ≥ 1.',
+ },
+ },
+ ],
+ ]);
+ });
+ });
+ });
+
+ describe('executeRatioAlert', () => {
+ before(() => esArchiver.load('x-pack/test/functional/es_archives/infra/ten_thousand_plus'));
+ after(() => esArchiver.unload('x-pack/test/functional/es_archives/infra/ten_thousand_plus'));
+
+ describe('without group by', () => {
+ it('should work', async () => {
+ const timestamp = new Date(DATES.ten_thousand_plus.max);
+ const alertFactory = sinon.fake();
+ const ruleParams = {
+ count: {
+ comparator: Comparator.GT_OR_EQ,
+ value: 0.5,
+ },
+ timeUnit: 'm' as TimeUnit,
+ timeSize: 5,
+ criteria: [
+ [{ field: 'event.dataset', comparator: Comparator.EQ, value: 'nginx.error' }],
+ [{ field: 'event.dataset', comparator: Comparator.NOT_EQ, value: 'nginx.error' }],
+ ] as RatioCriteria,
+ };
+ await executeRatioAlert(
+ ruleParams,
+ '@timestamp',
+ 'filebeat-*',
+ {},
+ esClient,
+ alertFactory,
+ timestamp.valueOf()
+ );
+ expect(alertFactory.callCount).to.equal(1);
+ expect(alertFactory.getCall(0).args).to.eql([
+ '*',
+ 'The ratio of selected logs is 0.5526081141328578 in the last 5 mins. Alert when ≥ 0.5.',
+ 0.5526081141328578,
+ 0.5,
+ [
+ {
+ actionGroup: 'logs.threshold.fired',
+ context: {
+ denominatorConditions: 'event.dataset does not equal nginx.error',
+ group: null,
+ isRatio: true,
+ numeratorConditions: 'event.dataset equals nginx.error',
+ ratio: 0.5526081141328578,
+ reason:
+ 'The ratio of selected logs is 0.5526081141328578 in the last 5 mins. Alert when ≥ 0.5.',
+ },
+ },
+ ],
+ ]);
+ });
+ });
+
+ describe('with group by', () => {
+ it('should work', async () => {
+ const timestamp = new Date(DATES.ten_thousand_plus.max);
+ const alertFactory = sinon.fake();
+ const ruleParams = {
+ count: {
+ comparator: Comparator.GT_OR_EQ,
+ value: 0.5,
+ },
+ timeUnit: 'm' as TimeUnit,
+ timeSize: 5,
+ groupBy: ['event.category'],
+ criteria: [
+ [{ field: 'event.dataset', comparator: Comparator.EQ, value: 'nginx.error' }],
+ [{ field: 'event.dataset', comparator: Comparator.NOT_EQ, value: 'nginx.error' }],
+ ] as RatioCriteria,
+ };
+ await executeRatioAlert(
+ ruleParams,
+ '@timestamp',
+ 'filebeat-*',
+ {},
+ esClient,
+ alertFactory,
+ timestamp.valueOf()
+ );
+ expect(alertFactory.callCount).to.equal(1);
+ expect(alertFactory.getCall(0).args).to.eql([
+ 'web',
+ 'The ratio of selected logs is 0.5526081141328578 in the last 5 mins for web. Alert when ≥ 0.5.',
+ 0.5526081141328578,
+ 0.5,
+ [
+ {
+ actionGroup: 'logs.threshold.fired',
+ context: {
+ denominatorConditions: 'event.dataset does not equal nginx.error',
+ group: 'web',
+ isRatio: true,
+ numeratorConditions: 'event.dataset equals nginx.error',
+ ratio: 0.5526081141328578,
+ reason:
+ 'The ratio of selected logs is 0.5526081141328578 in the last 5 mins for web. Alert when ≥ 0.5.',
+ },
+ },
+ ],
+ ]);
+ });
+ });
+ });
+ });
+}
From 82e7356f027bf9189e6aa172decca559d72622f2 Mon Sep 17 00:00:00 2001
From: Tim Sullivan
Date: Mon, 11 Apr 2022 12:15:01 -0700
Subject: [PATCH 17/75] [Screenshotting] Ensure worker.js content contents are
compiled in build (#129796)
* [Screenshotting] Expose packageInfo to pdf maker for dist data
* somehow use `dist` in the pdfmaker?
* use worker_src_harness exclusively when running from source
* Update pdfmaker.ts
* Update x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/pdfmaker.ts
Co-authored-by: Michael Dokolin
* [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix'
Co-authored-by: Michael Dokolin
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../screenshotting/server/formats/pdf/index.ts | 4 +++-
.../server/formats/pdf/pdf_maker/index.ts | 6 ++++--
.../integration_tests/pdfmaker.test.ts | 17 +++++++++++++----
.../server/formats/pdf/pdf_maker/pdfmaker.ts | 12 ++++++++++--
.../{worker.js => worker_src_harness.js} | 5 +++++
x-pack/plugins/screenshotting/server/plugin.ts | 5 ++++-
.../server/screenshots/index.test.ts | 14 ++++++++++++--
.../screenshotting/server/screenshots/index.ts | 5 +++--
8 files changed, 54 insertions(+), 14 deletions(-)
rename x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/{worker.js => worker_src_harness.js} (64%)
diff --git a/x-pack/plugins/screenshotting/server/formats/pdf/index.ts b/x-pack/plugins/screenshotting/server/formats/pdf/index.ts
index 7364ec210313a..b7718155c5424 100644
--- a/x-pack/plugins/screenshotting/server/formats/pdf/index.ts
+++ b/x-pack/plugins/screenshotting/server/formats/pdf/index.ts
@@ -7,7 +7,7 @@
import { groupBy } from 'lodash';
import type { Values } from '@kbn/utility-types';
-import type { Logger } from 'src/core/server';
+import type { Logger, PackageInfo } from 'src/core/server';
import type { LayoutParams } from '../../../common';
import { LayoutTypes } from '../../../common';
import type { Layout } from '../../layouts';
@@ -93,6 +93,7 @@ function getTimeRange(results: CaptureResult['results']) {
export async function toPdf(
logger: Logger,
+ packageInfo: PackageInfo,
layout: Layout,
{ logo, title }: PdfScreenshotOptions,
{ metrics, results }: CaptureResult
@@ -104,6 +105,7 @@ export async function toPdf(
results,
layout,
logo,
+ packageInfo,
logger,
});
diff --git a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/index.ts b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/index.ts
index ce5ea3cab813c..2c5439267ffc4 100644
--- a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/index.ts
+++ b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/index.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import type { Logger } from 'src/core/server';
+import type { Logger, PackageInfo } from 'src/core/server';
import { PdfMaker } from './pdfmaker';
import type { Layout } from '../../../layouts';
import { getTracker } from './tracker';
@@ -14,6 +14,7 @@ import type { CaptureResult } from '../../../screenshots';
interface PngsToPdfArgs {
results: CaptureResult['results'];
layout: Layout;
+ packageInfo: PackageInfo;
logger: Logger;
logo?: string;
title?: string;
@@ -24,9 +25,10 @@ export async function pngsToPdf({
layout,
logo,
title,
+ packageInfo,
logger,
}: PngsToPdfArgs): Promise<{ buffer: Buffer; pages: number }> {
- const pdfMaker = new PdfMaker(layout, logo, logger);
+ const pdfMaker = new PdfMaker(layout, logo, packageInfo, logger);
const tracker = getTracker();
if (title) {
pdfMaker.setTitle(title);
diff --git a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/integration_tests/pdfmaker.test.ts b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/integration_tests/pdfmaker.test.ts
index d3c9f2003dd4e..e08cf808abbc5 100644
--- a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/integration_tests/pdfmaker.test.ts
+++ b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/integration_tests/pdfmaker.test.ts
@@ -7,11 +7,12 @@
/* eslint-disable max-classes-per-file */
+import { PackageInfo } from 'kibana/server';
import path from 'path';
import { loggingSystemMock } from 'src/core/server/mocks';
import { isUint8Array } from 'util/types';
-import { createMockLayout } from '../../../../layouts/mock';
import { errors } from '../../../../../common';
+import { createMockLayout } from '../../../../layouts/mock';
import { PdfMaker } from '../pdfmaker';
const imageBase64 = Buffer.from(
@@ -23,11 +24,19 @@ describe('PdfMaker', () => {
let layout: ReturnType;
let pdf: PdfMaker;
let logger: ReturnType;
+ let packageInfo: Readonly;
beforeEach(() => {
layout = createMockLayout();
logger = loggingSystemMock.createLogger();
- pdf = new PdfMaker(layout, undefined, logger);
+ packageInfo = {
+ branch: 'screenshot-test',
+ buildNum: 567891011,
+ buildSha: 'screenshot-dfdfed0a',
+ dist: false,
+ version: '1000.0.0',
+ };
+ pdf = new PdfMaker(layout, undefined, packageInfo, logger);
});
describe('generate', () => {
@@ -56,14 +65,14 @@ describe('PdfMaker', () => {
protected workerMaxOldHeapSizeMb = 2;
protected workerMaxYoungHeapSizeMb = 2;
protected workerModulePath = path.resolve(__dirname, './memory_leak_worker.js');
- })(layout, undefined, logger);
+ })(layout, undefined, packageInfo, logger);
await expect(leakyMaker.generate()).rejects.toBeInstanceOf(errors.PdfWorkerOutOfMemoryError);
});
it('restarts the PDF worker if it crashes', async () => {
const buggyMaker = new (class BuggyPdfMaker extends PdfMaker {
protected workerModulePath = path.resolve(__dirname, './buggy_worker.js');
- })(layout, undefined, logger);
+ })(layout, undefined, packageInfo, logger);
await expect(buggyMaker.generate()).rejects.toThrowError(new Error('This is a bug'));
await expect(buggyMaker.generate()).rejects.toThrowError(new Error('This is a bug'));
diff --git a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/pdfmaker.ts b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/pdfmaker.ts
index f32bec1e3ed38..a10f259e5c9e5 100644
--- a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/pdfmaker.ts
+++ b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/pdfmaker.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import type { Logger } from 'src/core/server';
+import type { Logger, PackageInfo } from 'src/core/server';
import { SerializableRecord } from '@kbn/utility-types';
import path from 'path';
import { Content, ContentImage, ContentText } from 'pdfmake/interfaces';
@@ -34,7 +34,7 @@ export class PdfMaker {
private worker?: Worker;
private pageCount: number = 0;
- protected workerModulePath = path.resolve(__dirname, './worker.js');
+ protected workerModulePath: string;
/**
* The maximum heap size for old memory region of the worker thread.
@@ -65,10 +65,18 @@ export class PdfMaker {
constructor(
private readonly layout: Layout,
private readonly logo: string | undefined,
+ { dist }: PackageInfo,
private readonly logger: Logger
) {
this.title = '';
this.content = [];
+
+ // running in dist: `worker.ts` becomes `worker.js`
+ // running in source: `worker_src_harness.ts` needs to be wrapped in JS and have a ts-node environment initialized.
+ this.workerModulePath = path.resolve(
+ __dirname,
+ dist ? './worker.js' : './worker_src_harness.js'
+ );
}
_addContents(contents: Content[]) {
diff --git a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker.js b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker_src_harness.js
similarity index 64%
rename from x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker.js
rename to x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker_src_harness.js
index d3dfa3e9accf8..e180c130bc4af 100644
--- a/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker.js
+++ b/x-pack/plugins/screenshotting/server/formats/pdf/pdf_maker/worker_src_harness.js
@@ -5,5 +5,10 @@
* 2.0.
*/
+/**
+ * This file is the harness for importing worker.ts with Kibana running in dev mode.
+ * The TS file needs to be compiled on the fly, unlike when Kibana is running as a dist.
+ */
+
require('../../../../../../../src/setup_node_env');
require('./worker.ts');
diff --git a/x-pack/plugins/screenshotting/server/plugin.ts b/x-pack/plugins/screenshotting/server/plugin.ts
index 3f97de22d5e4b..2f675335d4393 100755
--- a/x-pack/plugins/screenshotting/server/plugin.ts
+++ b/x-pack/plugins/screenshotting/server/plugin.ts
@@ -11,6 +11,7 @@ import type {
CoreSetup,
CoreStart,
Logger,
+ PackageInfo,
Plugin,
PluginInitializerContext,
} from 'src/core/server';
@@ -45,6 +46,7 @@ export interface ScreenshottingStart {
export class ScreenshottingPlugin implements Plugin {
private config: ConfigType;
private logger: Logger;
+ private packageInfo: PackageInfo;
private screenshotMode!: ScreenshotModePluginSetup;
private browserDriverFactory!: Promise;
private screenshots!: Promise;
@@ -52,6 +54,7 @@ export class ScreenshottingPlugin implements Plugin) {
this.logger = context.logger.get();
this.config = context.config.get();
+ this.packageInfo = context.env.packageInfo;
}
setup({ http }: CoreSetup, { screenshotMode }: SetupDeps) {
@@ -82,7 +85,7 @@ export class ScreenshottingPlugin implements Plugin {});
diff --git a/x-pack/plugins/screenshotting/server/screenshots/index.test.ts b/x-pack/plugins/screenshotting/server/screenshots/index.test.ts
index 84a0974b0f8bc..eef98ceea34ba 100644
--- a/x-pack/plugins/screenshotting/server/screenshots/index.test.ts
+++ b/x-pack/plugins/screenshotting/server/screenshots/index.test.ts
@@ -6,7 +6,7 @@
*/
import { of, throwError } from 'rxjs';
-import type { Logger } from 'src/core/server';
+import type { Logger, PackageInfo } from 'src/core/server';
import { httpServiceMock } from 'src/core/server/mocks';
import {
SCREENSHOTTING_APP_ID,
@@ -31,6 +31,7 @@ describe('Screenshot Observable Pipeline', () => {
let http: ReturnType;
let layout: ReturnType;
let logger: jest.Mocked;
+ let packageInfo: Readonly;
let options: ScreenshotOptions;
let screenshots: Screenshots;
@@ -44,6 +45,13 @@ describe('Screenshot Observable Pipeline', () => {
error: jest.fn(),
info: jest.fn(),
} as unknown as jest.Mocked;
+ packageInfo = {
+ branch: 'screenshot-test',
+ buildNum: 567891011,
+ buildSha: 'screenshot-dfdfed0a',
+ dist: false,
+ version: '5000.0.0',
+ };
options = {
browserTimezone: 'UTC',
headers: {},
@@ -56,7 +64,9 @@ describe('Screenshot Observable Pipeline', () => {
},
urls: ['/welcome/home/start/index.htm'],
} as unknown as typeof options;
- screenshots = new Screenshots(driverFactory, logger, http, { poolSize: 1 } as ConfigType);
+ screenshots = new Screenshots(driverFactory, logger, packageInfo, http, {
+ poolSize: 1,
+ } as ConfigType);
jest.spyOn(Layouts, 'createLayout').mockReturnValue(layout);
diff --git a/x-pack/plugins/screenshotting/server/screenshots/index.ts b/x-pack/plugins/screenshotting/server/screenshots/index.ts
index 8672babe8b514..cfd5c76093d3b 100644
--- a/x-pack/plugins/screenshotting/server/screenshots/index.ts
+++ b/x-pack/plugins/screenshotting/server/screenshots/index.ts
@@ -22,7 +22,7 @@ import {
tap,
toArray,
} from 'rxjs/operators';
-import type { HttpServiceSetup, KibanaRequest, Logger } from 'src/core/server';
+import type { HttpServiceSetup, KibanaRequest, Logger, PackageInfo } from 'src/core/server';
import type { ExpressionAstExpression } from 'src/plugins/expressions/common';
import {
LayoutParams,
@@ -99,6 +99,7 @@ export class Screenshots {
constructor(
private readonly browserDriverFactory: HeadlessChromiumDriverFactory,
private readonly logger: Logger,
+ private readonly packageInfo: PackageInfo,
private readonly http: HttpServiceSetup,
{ poolSize }: ConfigType
) {
@@ -214,7 +215,7 @@ export class Screenshots {
mergeMap((result) => {
switch (options.format) {
case 'pdf':
- return toPdf(this.logger, layout, options, result);
+ return toPdf(this.logger, this.packageInfo, layout, options, result);
default:
return toPng(result);
}
From 0f7179a1438563c76a6bb5617d0af06be42c71d0 Mon Sep 17 00:00:00 2001
From: Kevin Logan <56395104+kevinlog@users.noreply.github.com>
Date: Mon, 11 Apr 2022 12:24:53 -0700
Subject: [PATCH 18/75] [Security Solution] Update advanced Policy check for
capture_mode (#129926)
---
.../management/pages/policy/models/advanced_policy_schema.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts b/x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts
index d5147f58d4f0b..7f86540e36426 100644
--- a/x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts
+++ b/x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts
@@ -880,7 +880,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [
'xpack.securitySolution.endpoint.policy.advanced.linux.advanced.kernel.capture_mode',
{
defaultMessage:
- 'Allows users to control whether kprobes or ebpf are used to gather data. Possible options are kprobes, ebpf, or auto. Default: auto',
+ 'Allows users to control whether kprobes or ebpf are used to gather data. Possible options are kprobes, ebpf, or auto. Default: kprobes',
}
),
},
From 4ff0a6e0af975782fed97119993d76df53715812 Mon Sep 17 00:00:00 2001
From: Frank Hassanabad
Date: Mon, 11 Apr 2022 13:32:50 -0600
Subject: [PATCH 19/75] Improved API documentation for exception lists
(#129828)
## Summary
Improves the API documentation for exception lists
### Checklist
Delete any items that are not applicable to this PR.
- [x] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials
---
.../exception_lists/exception_list_client.ts | 361 ++++++++++++------
.../exception_list_client_types.ts | 301 +++++++++++++++
2 files changed, 552 insertions(+), 110 deletions(-)
diff --git a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.ts b/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.ts
index d6fc1bfec8058..85dbd76e7b7c4 100644
--- a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.ts
+++ b/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.ts
@@ -96,13 +96,34 @@ import { findExceptionListsItemPointInTimeFinder } from './find_exception_list_i
import { findValueListExceptionListItemsPointInTimeFinder } from './find_value_list_exception_list_items_point_in_time_finder';
import { findExceptionListItemPointInTimeFinder } from './find_exception_list_item_point_in_time_finder';
+/**
+ * Class for use for exceptions that are with trusted applications or
+ * with rules.
+ */
export class ExceptionListClient {
+ /** User creating, modifying, deleting, or updating an exception list */
private readonly user: string;
+
+ /** Saved objects client to create, modify, delete, an exception list */
private readonly savedObjectsClient: SavedObjectsClientContract;
+
+ /** server extensions client that can be useful for injecting domain specific rules */
private readonly serverExtensionsClient: ExtensionPointStorageClientInterface;
+
+ /** Set to true to enable the server extension points, otherwise false */
private readonly enableServerExtensionPoints: boolean;
+
+ /** Optionally, the Kibana request which is useful for extension points */
private readonly request?: KibanaRequest;
+ /**
+ * Constructs the exception list
+ * @param options
+ * @param options.user The user associated with the action for exception list
+ * @param options.savedObjectsClient The saved objects client to create, modify, delete, an exception list
+ * @param options.serverExtensionsClient The server extensions client that can be useful for injecting domain specific rules
+ * @param options.request optionally, the Kibana request which is useful for extension points
+ */
constructor({
user,
savedObjectsClient,
@@ -142,10 +163,11 @@ export class ExceptionListClient {
/**
* Fetch an exception list parent container
- * @params listId {string | undefined} the "list_id" of an exception list
- * @params id {string | undefined} the "id" of an exception list
- * @params namespaceType {string | undefined} saved object namespace (single | agnostic)
- * @return {ExceptionListSchema | null} the found exception list or null if none exists
+ * @param options
+ * @param options.listId the "list_id" of an exception list
+ * @param options.id the "id" of an exception list
+ * @param options.namespaceType saved object namespace (single | agnostic)
+ * @returns The found exception list or null if none exists
*/
public getExceptionList = async ({
listId,
@@ -158,11 +180,12 @@ export class ExceptionListClient {
/**
* Fetch an exception list parent container
- * @params filter {sting | undefined} kql "filter" expression
- * @params listId {string | undefined} the "list_id" of an exception list
- * @params id {string | undefined} the "id" of an exception list
- * @params namespaceType {string | undefined} saved object namespace (single | agnostic)
- * @return {ExceptionListSummarySchema | null} summary of exception list item os types
+ * @param options
+ * @param options.filter kql "filter" expression
+ * @param options.listId the "list_id" of an exception list
+ * @param options.id the "id" of an exception list
+ * @param options.namespaceType saved object namespace (single | agnostic)
+ * @returns Summary of exception list item os types
*/
public getExceptionListSummary = async ({
filter,
@@ -190,10 +213,11 @@ export class ExceptionListClient {
/**
* Fetch an exception list item container
- * @params listId {string | undefined} the "list_id" of an exception list
- * @params id {string | undefined} the "id" of an exception list
- * @params namespaceType {string | undefined} saved object namespace (single | agnostic)
- * @return {ExceptionListSummarySchema | null} the found exception list item or null if none exists
+ * @param options
+ * @param options.itemId the "item_id" of an exception list (Either this or id has to be defined)
+ * @param options.id the "id" of an exception list (Either this or itemId has to be defined)
+ * @param options.namespaceType saved object namespace (single | agnostic)
+ * @returns the found exception list item or null if none exists
*/
public getExceptionListItem = async ({
itemId,
@@ -230,6 +254,7 @@ export class ExceptionListClient {
/**
* Create the Trusted Apps Agnostic list if it does not yet exist (`null` is returned if it does exist)
+ * @returns The exception list schema or null if it does not exist
*/
public createTrustedAppsList = async (): Promise => {
const { savedObjectsClient, user } = this;
@@ -244,6 +269,17 @@ export class ExceptionListClient {
* This is the same as "createListItem" except it applies specifically to the agnostic endpoint list and will
* auto-call the "createEndpointList" for you so that you have the best chance of the agnostic endpoint
* being there and existing before the item is inserted into the agnostic endpoint list.
+ * @param options
+ * @param options.comments The comments of the endpoint list item
+ * @param options.description The description of the endpoint list item
+ * @param options.entries The entries of the endpoint list item
+ * @param options.itemId The item id of the list item
+ * @param options.meta Optional meta data of the list item
+ * @param options.name The name of the list item
+ * @param options.osTypes The OS type of the list item
+ * @param options.tags Tags of the endpoint list item
+ * @param options.type The type of the endpoint list item (Default is "simple")
+ * @returns The exception list item created, otherwise null if not created
*/
public createEndpointListItem = async ({
comments,
@@ -280,6 +316,19 @@ export class ExceptionListClient {
* auto-call the "createEndpointList" for you so that you have the best chance of the endpoint
* being there if it did not exist before. If the list did not exist before, then creating it here will still cause a
* return of null but at least the list exists again.
+ * @param options
+ * @param options._version The version to update the endpoint list item to
+ * @param options.comments The comments of the endpoint list item
+ * @param options.description The description of the endpoint list item
+ * @param options.entries The entries of the endpoint list item
+ * @param options.id The id of the list item (Either this or itemId has to be defined)
+ * @param options.itemId The item id of the list item (Either this or id has to be defined)
+ * @param options.meta Optional meta data of the list item
+ * @param options.name The name of the list item
+ * @param options.osTypes The OS type of the list item
+ * @param options.tags Tags of the endpoint list item
+ * @param options.type The type of the endpoint list item (Default is "simple")
+ * @returns The exception list item updated, otherwise null if not updated
*/
public updateEndpointListItem = async ({
_version,
@@ -316,6 +365,10 @@ export class ExceptionListClient {
/**
* This is the same as "getExceptionListItem" except it applies specifically to the endpoint list.
+ * @param options
+ * @param options.itemId The item id (Either this or id has to be defined)
+ * @param options.id The id (Either this or itemId has to be defined)
+ * @returns The exception list item found, otherwise null
*/
public getEndpointListItem = async ({
itemId,
@@ -327,16 +380,17 @@ export class ExceptionListClient {
/**
* Create an exception list container
- * @params description {string} a description of the exception list
- * @params immutable {boolean} a description of the exception list
- * @params listId {string} the "list_id" of the exception list
- * @params meta {object | undefined}
- * @params name {string} the "name" of the exception list
- * @params namespaceType {string} saved object namespace (single | agnostic)
- * @params tags {array} user assigned tags of exception list
- * @params type {string} container type
- * @params version {number} document version
- * @return {ExceptionListSchema} the created exception list parent container
+ * @param options
+ * @param options.description a description of the exception list
+ * @param options.immutable True if it's a immutable list, otherwise false
+ * @param options.listId the "list_id" of the exception list
+ * @param options.meta Optional meta data to add to the exception list
+ * @param options.name the "name" of the exception list
+ * @param options.namespaceType saved object namespace (single | agnostic)
+ * @param options.tags user assigned tags of exception list
+ * @param options.type container type
+ * @param options.version document version
+ * @returns the created exception list parent container
*/
public createExceptionList = async ({
description,
@@ -367,17 +421,18 @@ export class ExceptionListClient {
/**
* Update an existing exception list container
- * @params _version {string | undefined} document version
- * @params id {string | undefined} the "id" of the exception list
- * @params description {string | undefined} a description of the exception list
- * @params listId {string | undefined} the "list_id" of the exception list
- * @params meta {object | undefined}
- * @params name {string | undefined} the "name" of the exception list
- * @params namespaceType {string} saved object namespace (single | agnostic)
- * @params tags {array | undefined} user assigned tags of exception list
- * @params type {string | undefined} container type
- * @params version {number | undefined} document version
- * @return {ExceptionListSchema | null} the updated exception list parent container
+ * @param options
+ * @param options._version document version
+ * @param options.id the "id" of the exception list
+ * @param options.description a description of the exception list
+ * @param options.listId the "list_id" of the exception list
+ * @param options.meta Optional meta object
+ * @param options.name the "name" of the exception list
+ * @param options.namespaceType saved object namespace (single | agnostic)
+ * @param options.tags user assigned tags of exception list
+ * @param options.type container type
+ * @param options.version document version, if undefined the current version number will be auto-incremented
+ * @returns the updated exception list parent container
*/
public updateExceptionList = async ({
_version,
@@ -410,10 +465,11 @@ export class ExceptionListClient {
/**
* Delete an exception list container by either id or list_id
- * @params listId {string | undefined} the "list_id" of an exception list
- * @params id {string | undefined} the "id" of an exception list
- * @params namespaceType {string} saved object namespace (single | agnostic)
- * @return {ExceptionListSchema | null} the deleted exception list or null if none exists
+ * @param options
+ * @param options.listId the "list_id" of an exception list (Either this or id has to be defined)
+ * @param options.id the "id" of an exception list (Either this or listId has to be defined)
+ * @param options.namespaceType saved object namespace (single | agnostic)
+ * @returns the deleted exception list or null if none exists
*/
public deleteExceptionList = async ({
id,
@@ -431,17 +487,19 @@ export class ExceptionListClient {
/**
* Create an exception list item container
- * @params description {string} a description of the exception list
- * @params entries {array} an array with the exception list item entries
- * @params itemId {string} the "item_id" of the exception list item
- * @params listId {string} the "list_id" of the parent exception list
- * @params meta {object | undefined}
- * @params name {string} the "name" of the exception list
- * @params namespaceType {string} saved object namespace (single | agnostic)
- * @params osTypes {array} item os types to apply
- * @params tags {array} user assigned tags of exception list
- * @params type {string} container type
- * @return {ExceptionListItemSchema} the created exception list item container
+ * @param options
+ * @param options.comments User comments for the exception list item
+ * @param options.description a description of the exception list
+ * @param options.entries an array with the exception list item entries
+ * @param options.itemId the "item_id" of the exception list item
+ * @param options.listId the "list_id" of the parent exception list
+ * @param options.meta Optional meta data about the list item
+ * @param options.name the "name" of the exception list
+ * @param options.namespaceType saved object namespace (single | agnostic)
+ * @param options.osTypes item os types to apply
+ * @param options.tags user assigned tags of exception list
+ * @param options.type container type
+ * @returns the created exception list item container
*/
public createExceptionListItem = async ({
comments,
@@ -494,19 +552,20 @@ export class ExceptionListClient {
/**
* Update an existing exception list item
- * @params _version {string | undefined} document version
- * @params comments {array} user comments attached to item
- * @params entries {array} item exception entries logic
- * @params id {string | undefined} the "id" of the exception list item
- * @params description {string | undefined} a description of the exception list
- * @params itemId {string | undefined} the "item_id" of the exception list item
- * @params meta {object | undefined}
- * @params name {string | undefined} the "name" of the exception list
- * @params namespaceType {string} saved object namespace (single | agnostic)
- * @params osTypes {array} item os types to apply
- * @params tags {array | undefined} user assigned tags of exception list
- * @params type {string | undefined} container type
- * @return {ExceptionListItemSchema | null} the updated exception list item or null if none exists
+ * @param options
+ * @param options._version document version
+ * @param options.comments user comments attached to item
+ * @param options.entries item exception entries logic
+ * @param options.id the "id" of the exception list item
+ * @param options.description a description of the exception list
+ * @param options.itemId the "item_id" of the exception list item
+ * @param options.meta Optional meta data about the exception list item
+ * @param options.name the "name" of the exception list
+ * @param options.namespaceType saved object namespace (single | agnostic)
+ * @param options.osTypes item os types to apply
+ * @param options.tags user assigned tags of exception list
+ * @param options.type container type
+ * @returns the updated exception list item or null if none exists
*/
public updateExceptionListItem = async ({
_version,
@@ -561,10 +620,11 @@ export class ExceptionListClient {
/**
* Delete an exception list item by either id or item_id
- * @params itemId {string | undefined} the "item_id" of an exception list item
- * @params id {string | undefined} the "id" of an exception list item
- * @params namespaceType {string} saved object namespace (single | agnostic)
- * @return {ExceptionListItemSchema | null} the deleted exception list item or null if none exists
+ * @param options
+ * @param options.itemId the "item_id" of an exception list item (Either this or id has to be defined)
+ * @param options.id the "id" of an exception list item (Either this or itemId has to be defined)
+ * @param options.namespaceType saved object namespace (single | agnostic)
+ * @returns the deleted exception list item or null if none exists
*/
public deleteExceptionListItem = async ({
id,
@@ -591,9 +651,9 @@ export class ExceptionListClient {
/**
* Delete an exception list item by id
- * @params id {string | undefined} the "id" of an exception list item
- * @params namespaceType {string} saved object namespace (single | agnostic)
- * @return {void}
+ * @param options
+ * @param options.id the "id" of an exception list item
+ * @param options.namespaceType saved object namespace (single | agnostic)
*/
public deleteExceptionListItemById = async ({
id,
@@ -618,6 +678,11 @@ export class ExceptionListClient {
/**
* This is the same as "deleteExceptionListItem" except it applies specifically to the endpoint list.
+ * Either id or itemId has to be defined to delete but not both is required. If both are provided, the id
+ * is preferred.
+ * @param options
+ * @param options.id The id of the endpoint list item (Either this or itemId has to be defined)
+ * @param options.itemId The item id of the endpoint list item (Either this or id has to be defined)
*/
public deleteEndpointListItem = async ({
id,
@@ -632,6 +697,20 @@ export class ExceptionListClient {
});
};
+ /**
+ * Finds an exception list item given a set of criteria.
+ * @param options
+ * @param options.listId The single list id to do the search against
+ * @param options.filter The filter to apply in the search
+ * @param options.perPage How many per page to return
+ * @param options.pit The Point in Time (pit) id if there is one, otherwise "undefined" can be send in
+ * @param options.page The page number or "undefined" if there is no page number to continue from
+ * @param options.searchAfter The search_after parameter if there is one, otherwise "undefined" can be sent in
+ * @param options.sortField The sort field string if there is one, otherwise "undefined" can be sent in
+ * @param options.sortOder The sort order string of "asc", "desc", otherwise "undefined" if there is no preference
+ * @param options.namespaceType Set the list type of either "agnostic" | "single"
+ * @returns The found exception list items or null if nothing is found
+ */
public findExceptionListItem = async ({
listId,
filter,
@@ -677,6 +756,20 @@ export class ExceptionListClient {
});
};
+ /**
+ * Finds exception lists items given a set of criteria.
+ * @param options
+ * @param options.listId The multiple list id's to do the search against
+ * @param options.filter The filter to apply in the search
+ * @param options.perPage How many per page to return
+ * @param options.pit The Point in Time (pit) id if there is one, otherwise "undefined" can be sent in
+ * @param options.page The page number or "undefined" if there is no page number to continue from
+ * @param options.searchAfter The search_after parameter if there is one, otherwise "undefined" can be sent in
+ * @param options.sortField The sort field string if there is one, otherwise "undefined" can be sent in
+ * @param options.sortOder The sort order string of "asc", "desc", otherwise "undefined" if there is no preference
+ * @param options.namespaceType Set the list type of either "agnostic" | "single"
+ * @returns The found exception lists items or null if nothing is found
+ */
public findExceptionListsItem = async ({
listId,
filter,
@@ -722,6 +815,18 @@ export class ExceptionListClient {
});
};
+ /**
+ * Finds value list exception items given a set of criteria.
+ * @param options
+ * @param options.perPage How many per page to return
+ * @param options.pit The Point in Time (pit) id if there is one, otherwise "undefined" can be send in
+ * @param options.page The page number or "undefined" if there is no page number to continue from
+ * @param options.searchAfter The search_after parameter if there is one, otherwise "undefined" can be sent in
+ * @param options.sortField The sort field string if there is one, otherwise "undefined" can be sent in
+ * @param options.sortOrder The sort order of "asc" or "desc", otherwise "undefined" can be sent in if there is no preference
+ * @param options.valueListId The value list id
+ * @returns The found value list exception list item or null if nothing is found
+ */
public findValueListExceptionListItems = async ({
perPage,
pit,
@@ -744,6 +849,19 @@ export class ExceptionListClient {
});
};
+ /**
+ * Finds exception lists given a set of criteria.
+ * @param options
+ * @param options.filter The filter to apply in the search
+ * @param options.perPage How many per page to return
+ * @param options.page The page number or "undefined" if there is no page number to continue from
+ * @param options.pit The Point in Time (pit) id if there is one, otherwise "undefined" can be sent in
+ * @param options.searchAfter The search_after parameter if there is one, otherwise "undefined" can be sent in
+ * @param options.sortField The sort field string if there is one, otherwise "undefined" can be sent in
+ * @param options.sortOrder The sort order of "asc" or "desc", otherwise "undefined" can be sent in
+ * @param options.namespaceType Set the list type of either "agnostic" | "single"
+ * @returns The found exception lists or null if nothing is found
+ */
public findExceptionList = async ({
filter,
perPage,
@@ -775,6 +893,15 @@ export class ExceptionListClient {
* a good guarantee that you will get an empty record set rather than null. I keep the null as the return value in
* the off chance that you still might somehow not get into a race condition where the endpoint list does
* not exist because someone deleted it in-between the initial create and then the find.
+ * @param options
+ * @param options.filter The filter to apply in the search
+ * @param options.perPage How many per page to return
+ * @param options.page The page number or "undefined" if there is no page number to continue from
+ * @param options.pit The Point in Time (pit) id if there is one, otherwise "undefined" can be sent in
+ * @param options.searchAfter The search_after parameter if there is one, otherwise "undefined" can be sent in
+ * @param options.sortField The sort field string if there is one, otherwise "undefined" can be sent in
+ * @param options.sortOrder The sort order of "asc" or "desc", otherwise "undefined" can be sent in
+ * @returns The found exception list items or null if nothing is found
*/
public findEndpointListItem = async ({
filter,
@@ -803,10 +930,11 @@ export class ExceptionListClient {
/**
* Export an exception list parent container and it's items
- * @params listId {string | undefined} the "list_id" of an exception list
- * @params id {string | undefined} the "id" of an exception list
- * @params namespaceType {string | undefined} saved object namespace (single | agnostic)
- * @return {ExportExceptionListAndItemsReturn | null} the ndjson of the list and items to export or null if none exists
+ * @param options
+ * @param options.listId the "list_id" of an exception list
+ * @param options.id the "id" of an exception list
+ * @param options.namespaceType saved object namespace (single | agnostic)
+ * @returns the ndjson of the list and items to export or null if none exists
*/
public exportExceptionListAndItems = async ({
listId,
@@ -837,10 +965,11 @@ export class ExceptionListClient {
/**
* Import exception lists parent containers and items as stream
- * @params exceptionsToImport {stream} ndjson stream of lists and items
- * @params maxExceptionsImportSize {number} the max number of lists and items to import, defaults to 10,000
- * @params overwrite {boolean} whether or not to overwrite an exception list with imported list if a matching list_id found
- * @return {ImportExceptionsResponseSchema} summary of imported count and errors
+ * @param options
+ * @param options.exceptionsToImport ndjson stream of lists and items
+ * @param options.maxExceptionsImportSize the max number of lists and items to import, defaults to 10,000
+ * @param options.overwrite whether or not to overwrite an exception list with imported list if a matching list_id found
+ * @returns summary of imported count and errors
*/
public importExceptionListAndItems = async ({
exceptionsToImport,
@@ -874,10 +1003,11 @@ export class ExceptionListClient {
/**
* Import exception lists parent containers and items as array
- * @params exceptionsToImport {array} array of lists and items
- * @params maxExceptionsImportSize {number} the max number of lists and items to import, defaults to 10,000
- * @params overwrite {boolean} whether or not to overwrite an exception list with imported list if a matching list_id found
- * @return {ImportExceptionsResponseSchema} summary of imported count and errors
+ * @param options
+ * @param options.exceptionsToImport array of lists and items
+ * @param options.maxExceptionsImportSize the max number of lists and items to import, defaults to 10,000
+ * @param options.overwrite whether or not to overwrite an exception list with imported list if a matching list_id found
+ * @returns summary of imported count and errors
*/
public importExceptionListAndItemsAsArray = async ({
exceptionsToImport,
@@ -908,9 +1038,10 @@ export class ExceptionListClient {
/**
* Opens a point in time (PIT) for either exception lists or exception list items.
* See: https://www.elastic.co/guide/en/elasticsearch/reference/current/point-in-time-api.html
- * @params namespaceType {string} "agnostic" or "single" depending on which namespace you are targeting
- * @params options {Object} The saved object PIT options
- * @return {SavedObjectsOpenPointInTimeResponse} The point in time (PIT)
+ * @param options
+ * @param options.namespaceType "agnostic" or "single" depending on which namespace you are targeting
+ * @param options.options The saved object PIT options
+ * @returns The point in time (PIT)
*/
public openPointInTime = async ({
namespaceType,
@@ -927,8 +1058,9 @@ export class ExceptionListClient {
/**
* Closes a point in time (PIT) for either exception lists or exception list items.
* See: https://www.elastic.co/guide/en/elasticsearch/reference/current/point-in-time-api.html
- * @params pit {string} The point in time to close
- * @return {SavedObjectsOpenPointInTimeResponse} The point in time (PIT)
+ * @param options
+ * @param options.pit The point in time to close
+ * @returns The point in time (PIT)
*/
public closePointInTime = async ({
pit,
@@ -965,12 +1097,15 @@ export class ExceptionListClient {
* exe
* });
* ```
- * @param filter {string} Your filter
- * @param namespaceType {string} "agnostic" | "single" of your namespace
- * @param perPage {number} The number of items per page. Typical value should be 1_000 here. Never go above 10_000
- * @param maxSize {number of undefined} If given a max size, this will not exceeded. Otherwise if undefined is passed down, all records will be processed.
- * @param sortField {string} String of the field to sort against
- * @param sortOrder "asc" | "desc" The order to sort against
+ * @param options
+ * @param options.filter The filter to apply in the search
+ * @param options.listId The "list_id" to filter against and find against
+ * @param options.namespaceType "agnostic" | "single" of your namespace
+ * @param options.perPage The number of items per page. Typical value should be 1_000 here. Never go above 10_000
+ * @param options.maxSize If given a max size, this will not exceeded. Otherwise if undefined is passed down, all records will be processed.
+ * @param options.sortField String of the field to sort against
+ * @param options.sortOrder "asc" | "desc" The order to sort against, "undefined" if the order does not matter
+ * @param options.executeFunctionOnStream The function to execute which will have the streamed results
*/
public findExceptionListItemPointInTimeFinder = async ({
executeFunctionOnStream,
@@ -1021,12 +1156,14 @@ export class ExceptionListClient {
* exe
* });
* ```
- * @param filter {string} Your filter
- * @param namespaceType {string} "agnostic" | "single" of your namespace
- * @param perPage {number} The number of items per page. Typical value should be 1_000 here. Never go above 10_000
- * @param maxSize {number of undefined} If given a max size, this will not exceeded. Otherwise if undefined is passed down, all records will be processed.
- * @param sortField {string} String of the field to sort against
- * @param sortOrder "asc" | "desc" The order to sort against
+ * @param options
+ * @param options.filter The filter to apply in the search
+ * @param options.namespaceType "agnostic" | "single" of your namespace
+ * @param options.perPage The number of items per page. Typical value should be 1_000 here. Never go above 10_000
+ * @param options.maxSize If given a max size, this will not be exceeded. Otherwise if undefined is passed down, all records will be processed.
+ * @param options.sortField String of the field to sort against
+ * @param options.sortOrder "asc" | "desc" The order to sort against, "undefined" if the order does not matter
+ * @param options.executeFunctionOnStream The function to execute which will have the streamed results
*/
public findExceptionListPointInTimeFinder = async ({
executeFunctionOnStream,
@@ -1075,12 +1212,15 @@ export class ExceptionListClient {
* exe
* });
* ```
- * @param filter {string} Your filter
- * @param namespaceType {string} "agnostic" | "single" of your namespace
- * @param perPage {number} The number of items per page. Typical value should be 1_000 here. Never go above 10_000
- * @param maxSize {number of undefined} If given a max size, this will not exceeded. Otherwise if undefined is passed down, all records will be processed.
- * @param sortField {string} String of the field to sort against
- * @param sortOrder "asc" | "desc" The order to sort against
+ * @param options
+ * @param options.listId The "list_id" to find against
+ * @param options.filter The filter to apply in the search
+ * @param options.namespaceType "agnostic" | "single" of your namespace
+ * @param options.perPage The number of items per page. Typical value should be 1_000 here. Never go above 10_000
+ * @param options.maxSize If given a max size, this will not exceeded. Otherwise if undefined is passed down, all records will be processed.
+ * @param options.sortField String of the field to sort against
+ * @param options.sortOrder "asc" | "desc" The order to sort against, "undefined" if the order does not matter
+ * @param options.executeFunctionOnStream The function to execute which will have the streamed results
*/
public findExceptionListsItemPointInTimeFinder = async ({
listId,
@@ -1131,12 +1271,13 @@ export class ExceptionListClient {
* exe
* });
* ```
- * @param valueListId {string} Your value list id
- * @param namespaceType {string} "agnostic" | "single" of your namespace
- * @param perPage {number} The number of items per page. Typical value should be 1_000 here. Never go above 10_000
- * @param maxSize {number of undefined} If given a max size, this will not exceeded. Otherwise if undefined is passed down, all records will be processed.
- * @param sortField {string} String of the field to sort against
- * @param sortOrder "asc" | "desc" The order to sort against
+ * @param options
+ * @param options.valueListId The value list id
+ * @param options.namespaceType "agnostic" | "single" of your namespace
+ * @param options.perPage The number of items per page. Typical value should be 1_000 here. Never go above 10_000
+ * @param options.maxSize If given a max size, this will not exceeded. Otherwise if undefined is passed down, all records will be processed.
+ * @param options.sortField String of the field to sort against
+ * @param options.sortOrder "asc" | "desc" The order to sort against, "undefined" if the order does not matter
*/
public findValueListExceptionListItemsPointInTimeFinder = async ({
valueListId,
diff --git a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client_types.ts b/x-pack/plugins/lists/server/services/exception_lists/exception_list_client_types.ts
index 4c7820fc05f94..1f440415fef40 100644
--- a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client_types.ts
+++ b/x-pack/plugins/lists/server/services/exception_lists/exception_list_client_types.ts
@@ -62,9 +62,15 @@ import type {
import type { ExtensionPointStorageClientInterface } from '../extension_points';
+/**
+ * Constructor options to {@link ExceptionListClient:constructor}
+ */
export interface ConstructorOptions {
+ /** User creating, modifying, deleting, or updating an exception list */
user: string;
+ /** Saved objects client to create, modify, delete, an exception list */
savedObjectsClient: SavedObjectsClientContract;
+ /** server extensions client that can be useful for injecting domain specific rules */
serverExtensionsClient: ExtensionPointStorageClientInterface;
/** Set to `false` if wanting to disable executing registered server extension points. Default is true. */
enableServerExtensionPoints?: boolean;
@@ -72,257 +78,552 @@ export interface ConstructorOptions {
request?: KibanaRequest;
}
+/**
+ * ExceptionListClient.getExceptionList
+ * {@link ExceptionListClient.getExceptionList}
+ */
export interface GetExceptionListOptions {
+ /** the "list_id" of an exception list */
listId: ListIdOrUndefined;
+ /** the "id" of an exception list */
id: IdOrUndefined;
+ /** saved object namespace (single | agnostic) */
namespaceType: NamespaceType;
}
+/**
+ * ExceptionListClient.getExceptionListSummary
+ * {@link ExceptionListClient.getExceptionListSummary}
+ */
export interface GetExceptionListSummaryOptions {
+ /** kql "filter" expression */
filter: FilterOrUndefined;
+ /** the "list_id" of an exception list */
listId: ListIdOrUndefined;
+ /** the "id" of an exception list */
id: IdOrUndefined;
+ /** saved object namespace (single | agnostic) */
namespaceType: NamespaceType;
}
+/**
+ * ExceptionListClient.createExceptionList
+ * {@link ExceptionListClient.createExceptionList}
+ */
export interface CreateExceptionListOptions {
+ /** the "list_id" of the exception list */
listId: ListId;
+ /** saved object namespace (single | agnostic) */
namespaceType: NamespaceType;
+ /** the "name" of the exception list */
name: Name;
+ /** a description of the exception list */
description: Description;
+ /** Optional meta data to add to the exception list */
meta: MetaOrUndefined;
+ /** user assigned tags of exception list */
tags: Tags;
+ /** container type */
type: ExceptionListType;
+ /** True if it's a immutable list, otherwise false */
immutable: Immutable;
+ /** document version */
version: Version;
}
+/**
+ * ExceptionListClient.updateExceptionList
+ * {@link ExceptionListClient.updateExceptionList}
+ */
export interface UpdateExceptionListOptions {
+ /** document version */
_version: _VersionOrUndefined;
+ /** the "id" of the exception list */
id: IdOrUndefined;
+ /** the "list_id" of the exception list */
listId: ListIdOrUndefined;
+ /** saved object namespace (single | agnostic) */
namespaceType: NamespaceType;
+ /** the "name" of the exception list */
name: NameOrUndefined;
+ /** item os types to apply */
osTypes: OsTypeArray;
+ /** a description of the exception list */
description: DescriptionOrUndefined;
+ /** Optional meta object */
meta: MetaOrUndefined;
+ /** user assigned tags of exception list */
tags: TagsOrUndefined;
+ /** container type */
type: ExceptionListTypeOrUndefined;
+ /** document version, if undefined the current version number will be auto-incremented */
version: VersionOrUndefined;
}
+/**
+ * ExceptionListClient.deleteExceptionList
+ * {@link ExceptionListClient.deleteExceptionList}
+ */
export interface DeleteExceptionListOptions {
+ /* the "id" of an exception list (Either this or listId has to be defined) */
id: IdOrUndefined;
+ /** the "list_id" of an exception list (Either this or id has to be defined) */
listId: ListIdOrUndefined;
+ /** saved object namespace (single | agnostic) */
namespaceType: NamespaceType;
}
+/**
+ * ExceptionListClient.deleteExceptionListItem
+ * {@link ExceptionListClient.deleteExceptionListItem}
+ */
export interface DeleteExceptionListItemOptions {
+ /** the "id" of an exception list item (Either this or itemId has to be defined) */
id: IdOrUndefined;
+ /** the "item_id" of an exception list item (Either this or id has to be defined) */
itemId: ItemIdOrUndefined;
+ /** saved object namespace (single | agnostic) */
namespaceType: NamespaceType;
}
+/**
+ * ExceptionListClient.deleteExceptionListItemById
+ * {@link ExceptionListClient.deleteExceptionListItemById}
+ */
export interface DeleteExceptionListItemByIdOptions {
+ /** the "id" of an exception list item */
id: Id;
+ /** saved object namespace (single | agnostic) */
namespaceType: NamespaceType;
}
+/**
+ * ExceptionListClient.deleteEndpointListItem
+ * {@link ExceptionListClient.deleteEndpointListItem}
+ */
export interface DeleteEndpointListItemOptions {
+ /** The id of the endpoint list item (Either this or itemId has to be defined) */
id: IdOrUndefined;
+ /** The item id of the endpoint list item (Either this or id has to be defined) */
itemId: ItemIdOrUndefined;
}
+/**
+ * ExceptionListClient.getExceptionListItem
+ * {@link ExceptionListClient.getExceptionListItem}
+ */
export interface GetExceptionListItemOptions {
+ /** the "item_id" of an exception list (Either this or id has to be defined) */
itemId: ItemIdOrUndefined;
+ /** the "id" of an exception list (Either this or itemId has to be defined) */
id: IdOrUndefined;
+ /** saved object namespace (single | agnostic) */
namespaceType: NamespaceType;
}
+/**
+ * ExceptionListClient.getEndpointListItem
+ * {@link ExceptionListClient.getEndpointListItem}
+ */
export interface GetEndpointListItemOptions {
+ /** The item id (Either this or id has to be defined) */
itemId: ItemIdOrUndefined;
+ /** The id (Either this or itemId has to be defined) */
id: IdOrUndefined;
}
+/**
+ * ExceptionListClient.createExceptionListItem
+ * {@link ExceptionListClient.createExceptionListItem}
+ */
export interface CreateExceptionListItemOptions {
+ /** User comments for the exception list item */
comments: CreateCommentsArray;
+ /** an array with the exception list item entries */
entries: EntriesArray;
+ /** the "item_id" of the exception list item */
itemId: ItemId;
+ /** the "list_id" of the parent exception list */
listId: ListId;
+ /** saved object namespace (single | agnostic) */
namespaceType: NamespaceType;
+ /** the "name" of the exception list */
name: Name;
+ /** item os types to apply */
osTypes: OsTypeArray;
+ /** a description of the exception list */
description: Description;
+ /** Optional meta data about the list item */
meta: MetaOrUndefined;
+ /** user assigned tags of exception list */
tags: Tags;
+ /** container type */
type: ExceptionListItemType;
}
+/**
+ * ExceptionListClient.createEndpointListItem
+ * {@link ExceptionListClient.createEndpointListItem}
+ */
export interface CreateEndpointListItemOptions {
+ /** The comments of the endpoint list item */
comments: CreateCommentsArray;
+ /** The entries of the endpoint list item */
entries: EntriesArray;
+ /** The item id of the list item */
itemId: ItemId;
+ /** The name of the list item */
name: Name;
+ /** The description of the endpoint list item */
description: Description;
+ /** Optional meta data of the list item */
meta: MetaOrUndefined;
+ /** The OS type of the list item */
osTypes: OsTypeArray;
+ /** Tags of the endpoint list item */
tags: Tags;
+ /** The type of the endpoint list item (Default is "simple") */
type: ExceptionListItemType;
}
+/**
+ * ExceptionListClient.updateExceptionListItem
+ * {@link ExceptionListClient.updateExceptionListItem}
+ */
export interface UpdateExceptionListItemOptions {
+ /** document version */
_version: _VersionOrUndefined;
+ /** user comments attached to item */
comments: UpdateCommentsArray;
+ /** item exception entries logic */
entries: EntriesArray;
+ /** the "id" of the exception list item */
id: IdOrUndefined;
+ /** the "item_id" of the exception list item */
itemId: ItemIdOrUndefined;
+ /** saved object namespace (single | agnostic) */
namespaceType: NamespaceType;
+ /** the "name" of the exception list */
name: NameOrUndefined;
+ /** item os types to apply */
osTypes: OsTypeArray;
+ /** a description of the exception list */
description: DescriptionOrUndefined;
+ /** Optional meta data about the exception list item */
meta: MetaOrUndefined;
+ /** user assigned tags of exception list */
tags: TagsOrUndefined;
+ /** container type */
type: ExceptionListItemTypeOrUndefined;
}
+/**
+ * ExceptionListClient.updateEndpointListItem
+ * {@link ExceptionListClient.updateEndpointListItem}
+ */
export interface UpdateEndpointListItemOptions {
+ /** The version to update the endpoint list item to */
_version: _VersionOrUndefined;
+ /** The comments of the endpoint list item */
comments: UpdateCommentsArray;
+ /** The entries of the endpoint list item */
entries: EntriesArray;
+ /** The id of the list item (Either this or itemId has to be defined) */
id: IdOrUndefined;
+ /** The item id of the list item (Either this or id has to be defined) */
itemId: ItemIdOrUndefined;
+ /** The name of the list item */
name: NameOrUndefined;
+ /** The OS type of the list item */
osTypes: OsTypeArray;
+ /** The description of the endpoint list item */
description: DescriptionOrUndefined;
+ /** Optional meta data of the list item */
meta: MetaOrUndefined;
+ /** Tags of the endpoint list item */
tags: TagsOrUndefined;
+ /** The type of the endpoint list item (Default is "simple") */
type: ExceptionListItemTypeOrUndefined;
}
+/**
+ * ExceptionListClient.findExceptionListItem
+ * {@link ExceptionListClient.findExceptionListItem}
+ */
export interface FindExceptionListItemOptions {
+ /** The single list id to do the search against */
listId: ListId;
+ /** Set the list type of either "agnostic" | "single" */
namespaceType: NamespaceType;
+ /** The filter to apply in the search */
filter: FilterOrUndefined;
+ /** How many per page to return */
perPage: PerPageOrUndefined;
+ /** The Point in Time (pit) id if there is one, otherwise "undefined" can be send in */
pit?: PitOrUndefined;
+ /** The search_after parameter if there is one, otherwise "undefined" can be sent in */
searchAfter?: SearchAfterOrUndefined;
+ /** The page number or "undefined" if there is no page number to continue from */
page: PageOrUndefined;
+ /** The sort field string if there is one, otherwise "undefined" can be sent in */
sortField: SortFieldOrUndefined;
+ /** The sort order string of "asc", "desc", otherwise "undefined" if there is no preference */
sortOrder: SortOrderOrUndefined;
}
+/**
+ * ExceptionListClient.findEndpointListItem
+ * {@link ExceptionListClient.findEndpointListItem}
+ */
export interface FindEndpointListItemOptions {
+ /** The filter to apply in the search */
filter: FilterOrUndefined;
+ /** How many per page to return */
perPage: PerPageOrUndefined;
+ /** The Point in Time (pit) id if there is one, otherwise "undefined" can be sent in */
pit?: PitOrUndefined;
+ /** The search_after parameter if there is one, otherwise "undefined" can be sent in */
searchAfter?: SearchAfterOrUndefined;
+ /** The page number or "undefined" if there is no page number to continue from */
page: PageOrUndefined;
+ /** The sort field string if there is one, otherwise "undefined" can be sent in */
sortField: SortFieldOrUndefined;
+ /** The sort order of "asc" or "desc", otherwise "undefined" can be sent in */
sortOrder: SortOrderOrUndefined;
}
+/**
+ * ExceptionListClient.findExceptionListsItem
+ * {@link ExceptionListClient.findExceptionListsItem}
+ */
export interface FindExceptionListsItemOptions {
+ /** The multiple list id's to do the search against */
listId: NonEmptyStringArrayDecoded;
+ /** Set the list type of either "agnostic" | "single" */
namespaceType: NamespaceTypeArray;
+ /** The filter to apply in the search */
filter: EmptyStringArrayDecoded;
+ /** How many per page to return */
perPage: PerPageOrUndefined;
+ /** The Point in Time (pit) id if there is one, otherwise "undefined" can be sent in */
pit?: PitOrUndefined;
+ /** The search_after parameter if there is one, otherwise "undefined" can be sent in */
searchAfter?: SearchAfterOrUndefined;
+ /** The page number or "undefined" if there is no page number to continue from */
page: PageOrUndefined;
+ /** The sort field string if there is one, otherwise "undefined" can be sent in */
sortField: SortFieldOrUndefined;
+ /** The sort order string of "asc", "desc", otherwise "undefined" if there is no preference */
sortOrder: SortOrderOrUndefined;
}
+/**
+ * ExceptionListClient.findValueListExceptionListItems
+ * {@link ExceptionListClient.findValueListExceptionListItems}
+ */
export interface FindValueListExceptionListsItems {
+ /** The value list id */
valueListId: Id;
+ /** How many per page to return */
perPage: PerPageOrUndefined;
+ /** The Point in Time (pit) id if there is one, otherwise "undefined" can be send in */
pit?: PitOrUndefined;
+ /** The search_after parameter if there is one, otherwise "undefined" can be sent in */
searchAfter?: SearchAfterOrUndefined;
+ /** The page number or "undefined" if there is no page number to continue from */
page: PageOrUndefined;
+ /** The sort field string if there is one, otherwise "undefined" can be sent in */
sortField: SortFieldOrUndefined;
+ /** The sort order of "asc" or "desc", otherwise "undefined" can be sent in if there is no preference */
sortOrder: SortOrderOrUndefined;
}
+/**
+ * ExceptionListClient.findExceptionList
+ * {@link ExceptionListClient.findExceptionList}
+ */
export interface FindExceptionListOptions {
+ /** Set the list type of either "agnostic" | "single" */
namespaceType: NamespaceTypeArray;
+ /** The filter to apply in the search */
filter: FilterOrUndefined;
+ /** How many per page to return */
perPage: PerPageOrUndefined;
+ /** The page number or "undefined" if there is no page number to continue from */
page: PageOrUndefined;
+ /** The Point in Time (pit) id if there is one, otherwise "undefined" can be sent in */
pit?: PitOrUndefined;
+ /** The search_after parameter if there is one, otherwise "undefined" can be sent in */
searchAfter?: SearchAfterOrUndefined;
+ /** The sort field string if there is one, otherwise "undefined" can be sent in */
sortField: SortFieldOrUndefined;
+ /** The sort order of "asc" or "desc", otherwise "undefined" can be sent in */
sortOrder: SortOrderOrUndefined;
}
+/**
+ * ExceptionListClient.exportExceptionListAndItems
+ * {@link ExceptionListClient.exportExceptionListAndItems}
+ */
export interface ExportExceptionListAndItemsOptions {
+ /** the "list_id" of an exception list */
listId: ListIdOrUndefined;
+ /** the "id" of an exception list */
id: IdOrUndefined;
+ /** saved object namespace (single | agnostic) */
namespaceType: NamespaceType;
}
+/**
+ * Used to export list and items
+ */
export interface ExportExceptionListAndItemsReturn {
+ /** The exported data as ndjson */
exportData: string;
+ /** The exported data details such as counts and missing data */
exportDetails: ExportExceptionDetails;
}
+/**
+ * ExceptionListClient.importExceptionListAndItems
+ * {@link ExceptionListClient.importExceptionListAndItems}
+ */
export interface ImportExceptionListAndItemsOptions {
+ /** ndjson stream of lists and items */
exceptionsToImport: Readable;
+ /** the max number of lists and items to import, defaults to 10,000 */
maxExceptionsImportSize: number;
+ /** whether or not to overwrite an exception list with imported list if a matching list_id found */
overwrite: boolean;
}
+/**
+ * ExceptionListClient.importExceptionListAndItemsAsArray
+ * {@link ExceptionListClient.importExceptionListAndItemsAsArray}
+ */
export interface ImportExceptionListAndItemsAsArrayOptions {
+ /** array of lists and items */
exceptionsToImport: Array;
+ /** the max number of lists and items to import, defaults to 10,000 */
maxExceptionsImportSize: number;
+ /** whether or not to overwrite an exception list with imported list if a matching list_id found */
overwrite: boolean;
}
+/**
+ * ExceptionListClient.openPointInTime
+ * {@link ExceptionListClient.openPointInTime}
+ */
export interface OpenPointInTimeOptions {
+ /** "agnostic" or "single" depending on which namespace you are targeting */
namespaceType: NamespaceType;
+ /** The saved object PIT options */
options: SavedObjectsOpenPointInTimeOptions | undefined;
}
+/**
+ * ExceptionListClient.closePointInTime
+ * {@link ExceptionListClient.closePointInTime}
+ */
export interface ClosePointInTimeOptions {
+ /** The point in time to close */
pit: PitId;
}
+/**
+ * ExceptionListClient.findExceptionListItemPointInTimeFinder
+ * {@link ExceptionListClient.findExceptionListItemPointInTimeFinder}
+ */
export interface FindExceptionListItemPointInTimeFinderOptions {
+ /** The "list_id" to filter against and find against */
listId: ListId;
+ /** "agnostic" | "single" of your namespace */
namespaceType: NamespaceType;
+ /** The filter to apply in the search */
filter: FilterOrUndefined;
+ /** The number of items per page. Typical value should be 1_000 here. Never go above 10_000 */
perPage: PerPageOrUndefined;
+ /** String of the field to sort against */
sortField: SortFieldOrUndefined;
+ /** "asc" | "desc" The order to sort against, "undefined" if the order does not matter */
sortOrder: SortOrderOrUndefined;
+ /**
+ * The function to execute which will have the streamed results
+ * @param response The streaming response
+ */
executeFunctionOnStream: (response: FoundExceptionListItemSchema) => void;
+ /** If given a max size, this will not be exceeded. Otherwise if undefined is passed down, all records will be processed. */
maxSize: MaxSizeOrUndefined;
}
+/**
+ * ExceptionListClient.findExceptionListPointInTimeFinder
+ * {@link ExceptionListClient.findExceptionListPointInTimeFinder}
+ */
export interface FindExceptionListPointInTimeFinderOptions {
+ /** If given a max size, this will not be exceeded. Otherwise if undefined is passed down, all records will be processed. */
maxSize: MaxSizeOrUndefined;
+ /** "agnostic" | "single" of your namespace */
namespaceType: NamespaceTypeArray;
+ /** The filter to apply in the search */
filter: FilterOrUndefined;
+ /** The number of items per page. Typical value should be 1_000 here. Never go above 10_000 */
perPage: PerPageOrUndefined;
+ /** String of the field to sort against */
sortField: SortFieldOrUndefined;
+ /** "asc" | "desc" The order to sort against, "undefined" if the order does not matter */
sortOrder: SortOrderOrUndefined;
+ /**
+ * The function to execute which will have the streamed results
+ * @param response The streaming response
+ */
executeFunctionOnStream: (response: FoundExceptionListSchema) => void;
}
+/**
+ * ExceptionListClient.findExceptionListsItemPointInTimeFinder
+ * {@link ExceptionListClient.findExceptionListsItemPointInTimeFinder}
+ */
export interface FindExceptionListItemsPointInTimeFinderOptions {
+ /** The "list_id" to find against */
listId: NonEmptyStringArrayDecoded;
+ /** "agnostic" | "single" of your namespace */
namespaceType: NamespaceTypeArray;
+ /** The filter to apply in the search */
filter: EmptyStringArrayDecoded;
+ /** The number of items per page. Typical value should be 1_000 here. Never go above 10_000 */
perPage: PerPageOrUndefined;
+ /** String of the field to sort against */
sortField: SortFieldOrUndefined;
+ /* "asc" | "desc" The order to sort against */
sortOrder: SortOrderOrUndefined;
+ /**
+ * The function to execute which will have the streamed results
+ * @param response The streaming response
+ */
executeFunctionOnStream: (response: FoundExceptionListItemSchema) => void;
+ /** If given a max size, this will not exceeded. Otherwise if undefined is passed down, all records will be processed. */
maxSize: MaxSizeOrUndefined;
}
+/**
+ * ExceptionListClient.findValueListExceptionListItemsPointInTimeFinder
+ * {@link ExceptionListClient.findValueListExceptionListItemsPointInTimeFinder}
+ */
export interface FindValueListExceptionListsItemsPointInTimeFinder {
+ /** The value list id */
valueListId: Id;
+ /** The number of items per page. Typical value should be 1_000 here. Never go above 10_000 */
perPage: PerPageOrUndefined;
+ /** String of the field to sort against */
sortField: SortFieldOrUndefined;
+ /** "asc" | "desc" The order to sort against, "undefined" if the order does not matter */
sortOrder: SortOrderOrUndefined;
+ /**
+ * The function to execute which will have the streamed results
+ * @param response The streaming response
+ */
executeFunctionOnStream: (response: FoundExceptionListItemSchema) => void;
+ /** If given a max size, this will not exceeded. Otherwise if undefined is passed down, all records will be processed. */
maxSize: MaxSizeOrUndefined;
}
From 268470a4406c1d3428f65ac4f82526c7e00c2b3f Mon Sep 17 00:00:00 2001
From: Davis Plumlee <56367316+dplumlee@users.noreply.github.com>
Date: Mon, 11 Apr 2022 15:34:58 -0400
Subject: [PATCH 20/75] [Security Solution] Rule Preview Table Follow-up
(#128981)
---
.../common/detection_engine/constants.ts | 2 +-
.../common/types/timeline/index.ts | 2 +
.../cypress/tasks/create_new_rule.ts | 4 +-
.../event_details/alert_summary_view.test.tsx | 9 +
.../components/event_details/columns.test.tsx | 13 ++
.../event_details/event_details.test.tsx | 15 ++
.../event_fields_browser.test.tsx | 19 ++
.../event_details/overview/index.test.tsx | 19 ++
.../utils/timeline/use_show_timeline.tsx | 2 +-
.../alerts_table/default_config.tsx | 18 +-
.../components/rules/rule_preview/helpers.ts | 2 +-
.../components/rules/rule_preview/index.tsx | 10 +-
.../rule_preview/preview_histogram.test.tsx | 90 +++-------
.../rules/rule_preview/preview_histogram.tsx | 106 +++++------
.../preview_table_cell_renderer.test.tsx | 167 ++++++++++++++++++
.../preview_table_cell_renderer.tsx | 1 +
.../rules/rule_preview/translations.ts | 21 ++-
.../rule_preview/use_preview_histogram.tsx | 11 +-
.../security_solution_detections/columns.ts | 51 ++++--
.../side_panel/event_details/index.test.tsx | 9 +
.../timelines/common/types/timeline/index.ts | 2 +
.../components/t_grid/integrated/index.tsx | 2 +-
.../translations/translations/fr-FR.json | 3 -
.../translations/translations/ja-JP.json | 3 -
.../translations/translations/zh-CN.json | 3 -
.../detection_engine_api_integration/utils.ts | 4 +-
26 files changed, 418 insertions(+), 170 deletions(-)
create mode 100644 x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_table_cell_renderer.test.tsx
diff --git a/x-pack/plugins/security_solution/common/detection_engine/constants.ts b/x-pack/plugins/security_solution/common/detection_engine/constants.ts
index b61cd34dc4790..6a6bf9df6d27a 100644
--- a/x-pack/plugins/security_solution/common/detection_engine/constants.ts
+++ b/x-pack/plugins/security_solution/common/detection_engine/constants.ts
@@ -6,7 +6,7 @@
*/
export enum RULE_PREVIEW_INVOCATION_COUNT {
- HOUR = 20,
+ HOUR = 12,
DAY = 24,
WEEK = 168,
MONTH = 30,
diff --git a/x-pack/plugins/security_solution/common/types/timeline/index.ts b/x-pack/plugins/security_solution/common/types/timeline/index.ts
index d2e9c2a6715fe..caeeaa0c17bee 100644
--- a/x-pack/plugins/security_solution/common/types/timeline/index.ts
+++ b/x-pack/plugins/security_solution/common/types/timeline/index.ts
@@ -326,6 +326,7 @@ export enum TimelineId {
casePage = 'timeline-case',
test = 'test', // Reserved for testing purposes
alternateTest = 'alternateTest',
+ rulePreview = 'rule-preview',
}
export const TimelineIdLiteralRt = runtimeTypes.union([
@@ -339,6 +340,7 @@ export const TimelineIdLiteralRt = runtimeTypes.union([
runtimeTypes.literal(TimelineId.networkPageExternalAlerts),
runtimeTypes.literal(TimelineId.active),
runtimeTypes.literal(TimelineId.test),
+ runtimeTypes.literal(TimelineId.rulePreview),
]);
export type TimelineIdLiteral = runtimeTypes.TypeOf;
diff --git a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts
index 17f545c25c39c..ed69f1d18d5e6 100644
--- a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts
+++ b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts
@@ -327,9 +327,9 @@ export const fillDefineEqlRuleAndContinue = (rule: CustomRule) => {
cy.get(PREVIEW_HISTOGRAM)
.invoke('text')
.then((text) => {
- if (text !== 'Hits') {
+ if (text !== 'Rule Preview') {
cy.get(RULES_CREATION_PREVIEW).find(QUERY_PREVIEW_BUTTON).click({ force: true });
- cy.get(PREVIEW_HISTOGRAM).should('contain.text', 'Hits');
+ cy.get(PREVIEW_HISTOGRAM).should('contain.text', 'Rule Preview');
}
});
cy.get(TOAST_ERROR).should('not.exist');
diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.test.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.test.tsx
index 650b915f50214..fe8a3d00a6364 100644
--- a/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.test.tsx
@@ -82,6 +82,15 @@ describe('AlertSummaryView', () => {
expect(queryAllByTestId('hover-actions-filter-for').length).toEqual(0);
});
+ test('it does NOT render the action cell when readOnly is passed', () => {
+ const { queryAllByTestId } = render(
+
+
+
+ );
+ expect(queryAllByTestId('hover-actions-filter-for').length).toEqual(0);
+ });
+
test("render no investigation guide if it doesn't exist", async () => {
(useRuleWithFallback as jest.Mock).mockReturnValue({
rule: {
diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/columns.test.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/columns.test.tsx
index a37157905bef9..be197499a700b 100644
--- a/x-pack/plugins/security_solution/public/common/components/event_details/columns.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/event_details/columns.test.tsx
@@ -136,5 +136,18 @@ describe('getColumns', () => {
).toEqual('hover-actions-copy-button');
});
});
+
+ describe('does not render hover actions when readOnly prop is passed', () => {
+ test('it renders a filter for (+) button', () => {
+ actionsColumn = getColumns({ ...defaultProps, isReadOnly: true })[0] as Column;
+ const wrapper = mount(
+ {actionsColumn.render(testValue, testData)}
+ ) as ReactWrapper;
+
+ expect(wrapper.find('[data-test-subj="hover-actions-filter-for"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="hover-actions-filter-out"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="more-actions-agent.id"]').exists()).toBeFalsy();
+ });
+ });
});
});
diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx
index 14910c77d198c..f7df157ed4602 100644
--- a/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx
@@ -140,5 +140,20 @@ describe('EventDetails', () => {
alertsWrapper.find('[data-test-subj="threatIntelTab"]').first().simulate('click');
expect(alertsWrapper.find('[data-test-subj="no-enrichments-found"]').exists()).toEqual(true);
});
+ it('does not render if readOnly prop is passed', async () => {
+ const newProps = { ...defaultProps, isReadOnly: true };
+ wrapper = mount(
+
+
+
+ ) as ReactWrapper;
+ alertsWrapper = mount(
+
+
+
+ ) as ReactWrapper;
+ await waitFor(() => wrapper.update());
+ expect(alertsWrapper.find('[data-test-subj="threatIntelTab"]').exists()).toBeFalsy();
+ });
});
});
diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.test.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.test.tsx
index a05a9e36a24e9..dcb28eafb6ef8 100644
--- a/x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.test.tsx
@@ -132,6 +132,25 @@ describe('EventFieldsBrowser', () => {
expect(wrapper.find('[data-test-subj="more-actions-@timestamp"]').exists()).toBeTruthy();
});
+ test('it does not render hover actions when readOnly prop is passed', () => {
+ const wrapper = mount(
+
+
+
+ );
+
+ expect(wrapper.find('[data-test-subj="hover-actions-filter-for"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="hover-actions-filter-out"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="more-actions-@timestamp"]').exists()).toBeFalsy();
+ });
+
test('it renders a column toggle button', () => {
const wrapper = mount(
diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/overview/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/overview/index.test.tsx
index 0f241bace7663..52e038fa07c56 100644
--- a/x-pack/plugins/security_solution/public/common/components/event_details/overview/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/event_details/overview/index.test.tsx
@@ -29,6 +29,20 @@ describe('Event Details Overview Cards', () => {
getByText('Rule');
});
+ it('renders only readOnly cards', () => {
+ const { getByText, queryByText } = render(
+
+
+
+ );
+
+ getByText('Severity');
+ getByText('Risk Score');
+
+ expect(queryByText('Status')).not.toBeInTheDocument();
+ expect(queryByText('Rule')).not.toBeInTheDocument();
+ });
+
it('renders all cards it has data for', () => {
const { getByText, queryByText } = render(
@@ -194,3 +208,8 @@ const propsWithoutSeverity = {
browserFields: { kibana: { fields: fieldsWithoutSeverity } },
data: dataWithoutSeverity,
};
+
+const propsWithReadOnly = {
+ ...props,
+ isReadOnly: true,
+};
diff --git a/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx b/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx
index f3ee9cbd81c52..e24a4d0025aee 100644
--- a/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx
+++ b/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx
@@ -8,7 +8,7 @@
import { useState, useEffect } from 'react';
import { useRouteSpy } from '../route/use_route_spy';
-const hideTimelineForRoutes = [`/cases/configure`, '/administration'];
+const hideTimelineForRoutes = [`/cases/configure`, '/administration', 'rules/create'];
export const useShowTimeline = () => {
const [{ pageName, pathName }] = useRouteSpy();
diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.tsx
index 7dc3561628193..8ae7e358f280d 100644
--- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.tsx
@@ -16,7 +16,10 @@ import { RowRendererId } from '../../../../common/types/timeline';
import { Status } from '../../../../common/detection_engine/schemas/common/schemas';
import { SubsetTimelineModel } from '../../../timelines/store/timeline/model';
import { timelineDefaults } from '../../../timelines/store/timeline/defaults';
-import { columns } from '../../configurations/security_solution_detections/columns';
+import {
+ columns,
+ rulePreviewColumns,
+} from '../../configurations/security_solution_detections/columns';
export const buildAlertStatusFilter = (status: Status): Filter[] => {
const combinedQuery =
@@ -156,6 +159,19 @@ export const alertsDefaultModel: SubsetTimelineModel = {
excludedRowRendererIds: Object.values(RowRendererId),
};
+export const alertsPreviewDefaultModel: SubsetTimelineModel = {
+ ...alertsDefaultModel,
+ columns: rulePreviewColumns,
+ defaultColumns: rulePreviewColumns,
+ sort: [
+ {
+ columnId: 'kibana.alert.original_time',
+ columnType: 'number',
+ sortDirection: 'desc',
+ },
+ ],
+};
+
export const requiredFieldsForActions = [
'@timestamp',
'kibana.alert.workflow_status',
diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/helpers.ts b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/helpers.ts
index f4e58c0d34c74..a2c4d2b14cdc9 100644
--- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/helpers.ts
+++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/helpers.ts
@@ -234,7 +234,7 @@ export const getIsRulePreviewDisabled = ({
if (ruleType === 'machine_learning') {
return machineLearningJobId.length === 0;
}
- if (ruleType === 'eql') {
+ if (ruleType === 'eql' || ruleType === 'query' || ruleType === 'threshold') {
return queryBar.query.query.length === 0;
}
return false;
diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/index.tsx
index a870b837a7d33..1286f6d5758c7 100644
--- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/index.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/index.tsx
@@ -29,6 +29,13 @@ import { LoadingHistogram } from './loading_histogram';
import { FieldValueThreshold } from '../threshold_input';
import { isJobStarted } from '../../../../../common/machine_learning/helpers';
+const HelpTextComponent = (
+
+ {i18n.QUERY_PREVIEW_HELP_TEXT}
+ {i18n.QUERY_PREVIEW_DISCLAIMER}
+
+);
+
export interface RulePreviewProps {
index: string[];
isDisabled: boolean;
@@ -116,7 +123,7 @@ const RulePreviewComponent: React.FC = ({
<>
= ({
previewId={previewId}
addNoiseWarning={addNoiseWarning}
spaceId={spaceId}
- threshold={threshold}
index={index}
/>
)}
diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_histogram.test.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_histogram.test.tsx
index bf174984a3492..1f16ddf3f845e 100644
--- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_histogram.test.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_histogram.test.tsx
@@ -6,7 +6,7 @@
*/
import React from 'react';
-import { mount } from 'enzyme';
+import { render } from '@testing-library/react';
import * as i18n from '../rule_preview/translations';
import { useGlobalTime } from '../../../../common/containers/use_global_time';
@@ -14,10 +14,12 @@ import { TestProviders } from '../../../../common/mock';
import { usePreviewHistogram } from './use_preview_histogram';
import { PreviewHistogram } from './preview_histogram';
+import { ALL_VALUES_ZEROS_TITLE } from '../../../../common/components/charts/translation';
+jest.mock('../../../../common/lib/kibana');
jest.mock('../../../../common/containers/use_global_time');
jest.mock('./use_preview_histogram');
-jest.mock('../../../../common/lib/kibana');
+jest.mock('../../../../common/components/url_state/normalize_time_range.ts');
describe('PreviewHistogram', () => {
const mockSetQuery = jest.fn();
@@ -35,9 +37,9 @@ describe('PreviewHistogram', () => {
jest.clearAllMocks();
});
- test('it renders loader when isLoading is true', () => {
+ describe('when there is no data', () => {
(usePreviewHistogram as jest.Mock).mockReturnValue([
- true,
+ false,
{
inspect: { dsl: [], response: [] },
totalCount: 1,
@@ -47,42 +49,38 @@ describe('PreviewHistogram', () => {
},
]);
- const wrapper = mount(
-
-
-
- );
+ test('it renders an empty histogram and table', () => {
+ const wrapper = render(
+
+
+
+ );
- expect(wrapper.find('[data-test-subj="preview-histogram-loading"]').exists()).toBeTruthy();
- expect(wrapper.find('[data-test-subj="header-section-subtitle"]').text()).toEqual(
- i18n.QUERY_PREVIEW_SUBTITLE_LOADING
- );
+ expect(wrapper.findByText('hello grid')).toBeTruthy();
+ expect(wrapper.findByText(ALL_VALUES_ZEROS_TITLE)).toBeTruthy();
+ });
});
- test('it configures data and subtitle', () => {
+ test('it renders loader when isLoading is true', () => {
(usePreviewHistogram as jest.Mock).mockReturnValue([
- false,
+ true,
{
inspect: { dsl: [], response: [] },
- totalCount: 9154,
+ totalCount: 1,
refetch: jest.fn(),
- data: [
- { x: 1602247050000, y: 2314, g: 'All others' },
- { x: 1602247162500, y: 3471, g: 'All others' },
- { x: 1602247275000, y: 3369, g: 'All others' },
- ],
+ data: [],
buckets: [],
},
]);
- const wrapper = mount(
+ const wrapper = render(
{
);
- expect(wrapper.find('[data-test-subj="preview-histogram-loading"]').exists()).toBeFalsy();
- expect(wrapper.find('[data-test-subj="header-section-subtitle"]').text()).toEqual(
- i18n.QUERY_PREVIEW_TITLE(9154)
- );
- expect(
- (
- wrapper.find('[data-test-subj="preview-histogram-bar-chart"]').props() as {
- barChart: unknown;
- }
- ).barChart
- ).toEqual([
- {
- key: 'hits',
- value: [
- {
- g: 'All others',
- x: 1602247050000,
- y: 2314,
- },
- {
- g: 'All others',
- x: 1602247162500,
- y: 3471,
- },
- {
- g: 'All others',
- x: 1602247275000,
- y: 3369,
- },
- ],
- },
- ]);
+ expect(wrapper.findByTestId('preview-histogram-loading')).toBeTruthy();
+ expect(wrapper.findByText(i18n.QUERY_PREVIEW_SUBTITLE_LOADING)).toBeTruthy();
});
});
diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_histogram.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_histogram.tsx
index 326811783fc4a..2119ab75ee67b 100644
--- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_histogram.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_histogram.tsx
@@ -11,19 +11,20 @@ import { Unit } from '@kbn/datemath';
import { EuiFlexGroup, EuiFlexItem, EuiText, EuiSpacer, EuiLoadingChart } from '@elastic/eui';
import styled from 'styled-components';
import { Type } from '@kbn/securitysolution-io-ts-alerting-types';
+import { useDispatch, useSelector } from 'react-redux';
+import { eventsViewerSelector } from '../../../../common/components/events_viewer/selectors';
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features';
import { useKibana } from '../../../../common/lib/kibana';
import * as i18n from './translations';
import { useGlobalTime } from '../../../../common/containers/use_global_time';
-import { getHistogramConfig, getThresholdHistogramConfig, isNoisy } from './helpers';
+import { getHistogramConfig, isNoisy } from './helpers';
import { ChartSeriesConfigs, ChartSeriesData } from '../../../../common/components/charts/common';
import { Panel } from '../../../../common/components/panel';
import { HeaderSection } from '../../../../common/components/header_section';
import { BarChart } from '../../../../common/components/charts/barchart';
import { usePreviewHistogram } from './use_preview_histogram';
import { formatDate } from '../../../../common/components/super_date_picker';
-import { FieldValueThreshold } from '../threshold_input';
-import { alertsDefaultModel } from '../../alerts_table/default_config';
+import { alertsPreviewDefaultModel } from '../../alerts_table/default_config';
import { SourcererScopeName } from '../../../../common/store/sourcerer/model';
import { defaultRowRenderers } from '../../../../timelines/components/timeline/body/renderers';
import { TimelineId } from '../../../../../common/types';
@@ -35,6 +36,8 @@ import { PreviewRenderCellValue } from './preview_table_cell_renderer';
import { getPreviewTableControlColumn } from './preview_table_control_columns';
import { useGlobalFullScreen } from '../../../../common/containers/use_full_screen';
import { InspectButtonContainer } from '../../../../common/components/inspect';
+import { timelineActions } from '../../../../timelines/store/timeline';
+import { State } from '../../../../common/store';
const LoadingChart = styled(EuiLoadingChart)`
display: block;
@@ -55,7 +58,6 @@ interface PreviewHistogramProps {
previewId: string;
addNoiseWarning: () => void;
spaceId: string;
- threshold?: FieldValueThreshold;
ruleType: Type;
index: string[];
}
@@ -67,10 +69,10 @@ export const PreviewHistogram = ({
previewId,
addNoiseWarning,
spaceId,
- threshold,
ruleType,
index,
}: PreviewHistogramProps) => {
+ const dispatch = useDispatch();
const { setQuery, isInitializing } = useGlobalTime();
const { timelines: timelinesUi, cases } = useKibana().services;
const from = useMemo(() => `now-1${timeFrame}`, [timeFrame]);
@@ -78,34 +80,36 @@ export const PreviewHistogram = ({
const startDate = useMemo(() => formatDate(from), [from]);
const endDate = useMemo(() => formatDate(to), [to]);
const isEqlRule = useMemo(() => ruleType === 'eql', [ruleType]);
- const isThresholdRule = useMemo(() => ruleType === 'threshold', [ruleType]);
+ const isMlRule = useMemo(() => ruleType === 'machine_learning', [ruleType]);
- const [isLoading, { data, inspect, totalCount, refetch, buckets }] = usePreviewHistogram({
+ const [isLoading, { data, inspect, totalCount, refetch }] = usePreviewHistogram({
previewId,
startDate,
endDate,
spaceId,
- threshold: isThresholdRule ? threshold : undefined,
index,
ruleType,
});
const {
- columns,
- dataProviders,
- deletedEventIds,
- kqlMode,
- itemsPerPage,
- itemsPerPageOptions,
- graphEventId,
- sort,
- } = alertsDefaultModel;
+ timeline: {
+ columns,
+ dataProviders,
+ defaultColumns,
+ deletedEventIds,
+ itemsPerPage,
+ itemsPerPageOptions,
+ kqlMode,
+ sort,
+ } = alertsPreviewDefaultModel,
+ } = useSelector((state: State) => eventsViewerSelector(state, TimelineId.rulePreview));
const {
browserFields,
docValueFields,
indexPattern,
runtimeMappings,
+ dataViewId: selectedDataViewId,
loading: isLoadingIndexPattern,
} = useSourcererDataView(SourcererScopeName.detections);
@@ -129,42 +133,28 @@ export const PreviewHistogram = ({
}
}, [setQuery, inspect, isLoading, isInitializing, refetch, previewId]);
+ useEffect(() => {
+ dispatch(
+ timelineActions.createTimeline({
+ columns,
+ dataViewId: selectedDataViewId,
+ defaultColumns,
+ id: TimelineId.rulePreview,
+ indexNames: [`${DEFAULT_PREVIEW_INDEX}-${spaceId}`],
+ itemsPerPage,
+ sort,
+ })
+ );
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
const barConfig = useMemo(
(): ChartSeriesConfigs => getHistogramConfig(endDate, startDate, !isEqlRule),
[endDate, startDate, isEqlRule]
);
- const thresholdBarConfig = useMemo((): ChartSeriesConfigs => getThresholdHistogramConfig(), []);
-
const chartData = useMemo((): ChartSeriesData[] => [{ key: 'hits', value: data }], [data]);
- const { thresholdChartData, thresholdTotalCount } = useMemo((): {
- thresholdChartData: ChartSeriesData[];
- thresholdTotalCount: number;
- } => {
- const total = buckets.length;
- const dataBuckets = buckets.map<{ x: string; y: number; g: string }>(
- ({ key, doc_count: docCount }) => ({
- x: key,
- y: docCount,
- g: key,
- })
- );
- return {
- thresholdChartData: [{ key: 'hits', value: dataBuckets }],
- thresholdTotalCount: total,
- };
- }, [buckets]);
-
- const subtitle = useMemo(
- (): string =>
- isLoading
- ? i18n.QUERY_PREVIEW_SUBTITLE_LOADING
- : isThresholdRule
- ? i18n.QUERY_PREVIEW_THRESHOLD_WITH_FIELD_TITLE(thresholdTotalCount)
- : i18n.QUERY_PREVIEW_TITLE(totalCount),
- [isLoading, totalCount, thresholdTotalCount, isThresholdRule]
- );
const CasesContext = cases.ui.getCasesContext();
return (
@@ -176,7 +166,6 @@ export const PreviewHistogram = ({
id={`${ID}-${previewId}`}
title={i18n.QUERY_GRAPH_HITS_TITLE}
titleSize="xs"
- subtitle={subtitle}
/>
@@ -184,8 +173,8 @@ export const PreviewHistogram = ({
) : (
)}
@@ -194,7 +183,11 @@ export const PreviewHistogram = ({
<>
- {i18n.QUERY_PREVIEW_DISCLAIMER_MAX_SIGNALS}
+
+ {isMlRule
+ ? i18n.ML_PREVIEW_HISTOGRAM_DISCLAIMER
+ : i18n.PREVIEW_HISTOGRAM_DISCLAIMER}
+
>
@@ -213,13 +206,12 @@ export const PreviewHistogram = ({
deletedEventIds,
disabledCellActions: FIELDS_WITHOUT_CELL_ACTIONS,
docValueFields,
- end: to,
- entityType: 'alerts',
+ end: endDate,
+ entityType: 'events',
filters: [],
globalFullScreen,
- graphEventId,
hasAlertsCrud: false,
- id: TimelineId.detectionsPage,
+ id: TimelineId.rulePreview,
indexNames: [`${DEFAULT_PREVIEW_INDEX}-${spaceId}`],
indexPattern,
isLive: false,
@@ -233,7 +225,7 @@ export const PreviewHistogram = ({
runtimeMappings,
setQuery: () => {},
sort,
- start: from,
+ start: startDate,
tGridEventRenderedViewEnabled,
type: 'embedded',
leadingControlColumns: getPreviewTableControlColumn(1.5),
@@ -242,11 +234,11 @@ export const PreviewHistogram = ({
diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_table_cell_renderer.test.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_table_cell_renderer.test.tsx
new file mode 100644
index 0000000000000..37b03dbc3fd88
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_table_cell_renderer.test.tsx
@@ -0,0 +1,167 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { mount } from 'enzyme';
+import { cloneDeep } from 'lodash/fp';
+import React from 'react';
+
+import { mockBrowserFields } from '../../../../common/containers/source/mock';
+import { DragDropContextWrapper } from '../../../../common/components/drag_and_drop/drag_drop_context_wrapper';
+import { defaultHeaders, mockTimelineData, TestProviders } from '../../../../common/mock';
+import { PreviewTableCellRenderer } from './preview_table_cell_renderer';
+import { getColumnRenderer } from '../../../../timelines/components/timeline/body/renderers/get_column_renderer';
+import { DroppableWrapper } from '../../../../common/components/drag_and_drop/droppable_wrapper';
+import { BrowserFields } from '../../../../../../timelines/common/search_strategy';
+import { Ecs } from '../../../../../common/ecs';
+import { columnRenderers } from '../../../../timelines/components/timeline/body/renderers';
+
+jest.mock('../../../../common/lib/kibana');
+jest.mock('../../../../timelines/components/timeline/body/renderers/get_column_renderer');
+
+const getColumnRendererMock = getColumnRenderer as jest.Mock;
+const mockImplementation = {
+ renderColumn: jest.fn(),
+};
+
+describe('PreviewTableCellRenderer', () => {
+ const columnId = '@timestamp';
+ const eventId = '_id-123';
+ const isExpandable = true;
+ const isExpanded = true;
+ const linkValues = ['foo', 'bar', '@baz'];
+ const rowIndex = 3;
+ const colIndex = 0;
+ const setCellProps = jest.fn();
+ const timelineId = 'test';
+ const ecsData = {} as Ecs;
+ const browserFields = {} as BrowserFields;
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ getColumnRendererMock.mockImplementation(() => mockImplementation);
+ });
+
+ test('it invokes `getColumnRenderer` with the expected arguments', () => {
+ const data = cloneDeep(mockTimelineData[0].data);
+ const header = cloneDeep(defaultHeaders[0]);
+ const isDetails = true;
+
+ mount(
+
+
+
+
+
+
+
+ );
+
+ expect(getColumnRenderer).toBeCalledWith(header.id, columnRenderers, data);
+ });
+
+ test('if in tgrid expanded value, it invokes `renderColumn` with the expected arguments', () => {
+ const data = cloneDeep(mockTimelineData[0].data);
+ const header = cloneDeep(defaultHeaders[0]);
+ const isDetails = true;
+ const truncate = isDetails ? false : true;
+
+ mount(
+
+
+
+
+
+
+
+ );
+
+ expect(mockImplementation.renderColumn).toBeCalledWith({
+ asPlainText: false,
+ browserFields,
+ columnName: header.id,
+ ecsData,
+ eventId,
+ field: header,
+ isDetails,
+ isDraggable: true,
+ linkValues,
+ rowRenderers: undefined,
+ timelineId,
+ truncate,
+ values: ['2018-11-05T19:03:25.937Z'],
+ });
+ });
+
+ test('if in tgrid expanded value, it does not render any actions', () => {
+ const data = cloneDeep(mockTimelineData[0].data);
+ const header = cloneDeep(defaultHeaders[1]);
+ const isDetails = true;
+ const id = 'event.severity';
+ const wrapper = mount(
+
+
+
+
+
+
+
+ );
+
+ expect(
+ wrapper.find('[data-test-subj="data-grid-expanded-cell-value-actions"]').exists()
+ ).toBeFalsy();
+ });
+});
diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_table_cell_renderer.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_table_cell_renderer.tsx
index ab56bd3fbfe0d..0e9df27827e47 100644
--- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_table_cell_renderer.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/preview_table_cell_renderer.tsx
@@ -89,6 +89,7 @@ export const PreviewTableCellRenderer: React.FC = ({
const styledContentClassName = isDetails
? 'eui-textBreakWord'
: 'eui-displayInlineBlock eui-textTruncate';
+
return (
<>
diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/translations.ts b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/translations.ts
index 3acb533913cfd..81ff4b8cfc440 100644
--- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/translations.ts
+++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/translations.ts
@@ -54,7 +54,7 @@ export const QUERY_PREVIEW_LABEL = i18n.translate(
export const QUERY_PREVIEW_HELP_TEXT = i18n.translate(
'xpack.securitySolution.detectionEngine.queryPreview.queryPreviewHelpText',
{
- defaultMessage: 'Select a timeframe of data to preview query results',
+ defaultMessage: 'Select a timeframe of data to preview query results.',
}
);
@@ -73,9 +73,9 @@ export const THRESHOLD_QUERY_GRAPH_COUNT = i18n.translate(
);
export const QUERY_GRAPH_HITS_TITLE = i18n.translate(
- 'xpack.securitySolution.detectionEngine.queryPreview.queryGraphHitsTitle',
+ 'xpack.securitySolution.detectionEngine.queryPreview.queryPreviewTitle',
{
- defaultMessage: 'Hits',
+ defaultMessage: 'Rule Preview',
}
);
@@ -124,18 +124,25 @@ export const QUERY_PREVIEW_ERROR = i18n.translate(
);
export const QUERY_PREVIEW_DISCLAIMER = i18n.translate(
- 'xpack.securitySolution.detectionEngine.queryPreview.queryGraphDisclaimer',
+ 'xpack.securitySolution.detectionEngine.queryPreview.queryPreviewDisclaimer',
{
defaultMessage:
'Note: This preview excludes effects of rule exceptions and timestamp overrides.',
}
);
-export const QUERY_PREVIEW_DISCLAIMER_MAX_SIGNALS = i18n.translate(
- 'xpack.securitySolution.detectionEngine.queryPreview.queryGraphDisclaimerEql',
+export const PREVIEW_HISTOGRAM_DISCLAIMER = i18n.translate(
+ 'xpack.securitySolution.detectionEngine.queryPreview.histogramDisclaimer',
{
defaultMessage:
- 'Note: This preview excludes effects of rule exceptions and timestamp overrides, and is limited to 100 results.',
+ 'Note: Alerts with multiple event.category values will be counted more than once.',
+ }
+);
+
+export const ML_PREVIEW_HISTOGRAM_DISCLAIMER = i18n.translate(
+ 'xpack.securitySolution.detectionEngine.queryPreview.mlHistogramDisclaimer',
+ {
+ defaultMessage: 'Note: Alerts with multiple host.name values will be counted more than once.',
}
);
diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/use_preview_histogram.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/use_preview_histogram.tsx
index 0d63092ee4eef..d336c75bb5f49 100644
--- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/use_preview_histogram.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/use_preview_histogram.tsx
@@ -13,14 +13,12 @@ import { getEsQueryConfig } from '../../../../../../../../src/plugins/data/commo
import { useKibana } from '../../../../common/lib/kibana';
import { QUERY_PREVIEW_ERROR } from './translations';
import { DEFAULT_PREVIEW_INDEX } from '../../../../../common/constants';
-import { FieldValueThreshold } from '../threshold_input';
interface PreviewHistogramParams {
previewId: string | undefined;
endDate: string;
startDate: string;
spaceId: string;
- threshold?: FieldValueThreshold;
index: string[];
ruleType: Type;
}
@@ -30,7 +28,6 @@ export const usePreviewHistogram = ({
startDate,
endDate,
spaceId,
- threshold,
index,
ruleType,
}: PreviewHistogramParams) => {
@@ -47,9 +44,8 @@ export const usePreviewHistogram = ({
});
const stackByField = useMemo(() => {
- const stackByDefault = ruleType === 'machine_learning' ? 'host.name' : 'event.category';
- return threshold?.field[0] ?? stackByDefault;
- }, [threshold, ruleType]);
+ return ruleType === 'machine_learning' ? 'host.name' : 'event.category';
+ }, [ruleType]);
const matrixHistogramRequest = useMemo(() => {
return {
@@ -60,11 +56,10 @@ export const usePreviewHistogram = ({
indexNames: [`${DEFAULT_PREVIEW_INDEX}-${spaceId}`],
stackByField,
startDate,
- threshold,
includeMissingData: false,
skip: error != null,
};
- }, [startDate, endDate, filterQuery, spaceId, error, threshold, stackByField]);
+ }, [startDate, endDate, filterQuery, spaceId, error, stackByField]);
return useMatrixHistogramCombined(matrixHistogramRequest);
};
diff --git a/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/columns.ts b/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/columns.ts
index a7942642b830f..b542fa7d40c4a 100644
--- a/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/columns.ts
+++ b/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/columns.ts
@@ -16,25 +16,9 @@ import {
import * as i18n from '../../components/alerts_table/translations';
-/**
- * columns implements a subset of `EuiDataGrid`'s `EuiDataGridColumn` interface,
- * plus additional TGrid column properties
- */
-export const columns: Array<
+const baseColumns: Array<
Pick & ColumnHeaderOptions
> = [
- {
- columnHeaderType: defaultColumnHeaderType,
- id: '@timestamp',
- initialWidth: DEFAULT_DATE_COLUMN_MIN_WIDTH + 10,
- },
- {
- columnHeaderType: defaultColumnHeaderType,
- displayAsText: i18n.ALERTS_HEADERS_RULE,
- id: 'kibana.alert.rule.name',
- initialWidth: DEFAULT_COLUMN_MIN_WIDTH,
- linkField: 'kibana.alert.rule.uuid',
- },
{
columnHeaderType: defaultColumnHeaderType,
displayAsText: i18n.ALERTS_HEADERS_SEVERITY,
@@ -78,3 +62,36 @@ export const columns: Array<
id: 'destination.ip',
},
];
+
+/**
+ * columns implements a subset of `EuiDataGrid`'s `EuiDataGridColumn` interface,
+ * plus additional TGrid column properties
+ */
+export const columns: Array<
+ Pick & ColumnHeaderOptions
+> = [
+ {
+ columnHeaderType: defaultColumnHeaderType,
+ id: '@timestamp',
+ initialWidth: DEFAULT_DATE_COLUMN_MIN_WIDTH + 10,
+ },
+ {
+ columnHeaderType: defaultColumnHeaderType,
+ displayAsText: i18n.ALERTS_HEADERS_RULE,
+ id: 'kibana.alert.rule.name',
+ initialWidth: DEFAULT_COLUMN_MIN_WIDTH,
+ linkField: 'kibana.alert.rule.uuid',
+ },
+ ...baseColumns,
+];
+
+export const rulePreviewColumns: Array<
+ Pick & ColumnHeaderOptions
+> = [
+ {
+ columnHeaderType: defaultColumnHeaderType,
+ id: 'kibana.alert.original_time',
+ initialWidth: DEFAULT_DATE_COLUMN_MIN_WIDTH + 10,
+ },
+ ...baseColumns,
+];
diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.test.tsx
index bdb896e31cfa3..5147301b4ea5d 100644
--- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.test.tsx
@@ -167,4 +167,13 @@ describe('event details footer component', () => {
);
expect(wrapper.getByTestId('side-panel-flyout-footer')).toBeTruthy();
});
+ test("it doesn't render the take action dropdown when readOnly prop is passed", () => {
+ const wrapper = render(
+
+
+
+ );
+ const element = wrapper.queryByTestId('side-panel-flyout-footer');
+ expect(element).toBeNull();
+ });
});
diff --git a/x-pack/plugins/timelines/common/types/timeline/index.ts b/x-pack/plugins/timelines/common/types/timeline/index.ts
index cac24f65d0fd2..867264fa81546 100644
--- a/x-pack/plugins/timelines/common/types/timeline/index.ts
+++ b/x-pack/plugins/timelines/common/types/timeline/index.ts
@@ -322,6 +322,7 @@ export enum TimelineId {
casePage = 'timeline-case',
test = 'test', // Reserved for testing purposes
alternateTest = 'alternateTest',
+ rulePreview = 'rule-preview',
}
export const TimelineIdLiteralRt = runtimeTypes.union([
@@ -333,6 +334,7 @@ export const TimelineIdLiteralRt = runtimeTypes.union([
runtimeTypes.literal(TimelineId.networkPageExternalAlerts),
runtimeTypes.literal(TimelineId.active),
runtimeTypes.literal(TimelineId.test),
+ runtimeTypes.literal(TimelineId.rulePreview),
]);
export type TimelineIdLiteral = runtimeTypes.TypeOf;
diff --git a/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx b/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx
index 6f74fd1d2cb37..2991d80c7af0a 100644
--- a/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx
+++ b/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx
@@ -113,7 +113,7 @@ export interface TGridIntegratedProps {
filterStatus?: AlertStatus;
globalFullScreen: boolean;
// If truthy, the graph viewer (Resolver) is showing
- graphEventId: string | undefined;
+ graphEventId?: string;
graphOverlay?: React.ReactNode;
hasAlertsCrud: boolean;
height?: number;
diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json
index 687339109cbb0..175879805b251 100644
--- a/x-pack/plugins/translations/translations/fr-FR.json
+++ b/x-pack/plugins/translations/translations/fr-FR.json
@@ -20726,9 +20726,6 @@
"xpack.securitySolution.detectionEngine.pageTitle": "Moteur de détection",
"xpack.securitySolution.detectionEngine.panelSubtitleShowing": "Affichant",
"xpack.securitySolution.detectionEngine.queryPreview.queryGraphCountLabel": "Compte",
- "xpack.securitySolution.detectionEngine.queryPreview.queryGraphDisclaimer": "Remarque : cet aperçu exclut les effets d'exceptions aux règles et les remplacements d'horodatages.",
- "xpack.securitySolution.detectionEngine.queryPreview.queryGraphDisclaimerEql": "Remarque : cet aperçu exclut les effets d'exceptions aux règles et les remplacements d'horodatages, et est limité à 100 résultats.",
- "xpack.securitySolution.detectionEngine.queryPreview.queryGraphHitsTitle": "Résultats",
"xpack.securitySolution.detectionEngine.queryPreview.queryGraphPreviewError": "Erreur de récupération de l'aperçu",
"xpack.securitySolution.detectionEngine.queryPreview.queryGraphPreviewInspectTitle": "aperçu de la recherche",
"xpack.securitySolution.detectionEngine.queryPreview.queryGraphPreviewNoiseWarning": "Avertissement de bruit : cette règle peut générer beaucoup de bruit. Envisagez d'affiner votre recherche. La base est une progression linéaire comportant 1 alerte par heure.",
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 1527acb993bb4..fd11b97f873a7 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -23586,9 +23586,6 @@
"xpack.securitySolution.detectionEngine.pageTitle": "検出エンジン",
"xpack.securitySolution.detectionEngine.panelSubtitleShowing": "表示中",
"xpack.securitySolution.detectionEngine.queryPreview.queryGraphCountLabel": "カウント",
- "xpack.securitySolution.detectionEngine.queryPreview.queryGraphDisclaimer": "注:このプレビューは、ルール例外とタイムスタンプオーバーライドの効果を除外します。",
- "xpack.securitySolution.detectionEngine.queryPreview.queryGraphDisclaimerEql": "注:このプレビューは、ルール例外とタイムスタンプオーバーライドの効果を除外します。結果は100件に制限されます。",
- "xpack.securitySolution.detectionEngine.queryPreview.queryGraphHitsTitle": "ヒット数",
"xpack.securitySolution.detectionEngine.queryPreview.queryGraphPreviewError": "プレビュー取得エラー",
"xpack.securitySolution.detectionEngine.queryPreview.queryGraphPreviewInspectTitle": "クエリプレビュー",
"xpack.securitySolution.detectionEngine.queryPreview.queryGraphPreviewNoiseWarning": "ノイズ警告:このルールではノイズが多く生じる可能性があります。クエリを絞り込むことを検討してください。これは1時間ごとに1アラートという線形進行に基づいています。",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 70d58abb23a95..d3d6b3b18a8bd 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -23613,9 +23613,6 @@
"xpack.securitySolution.detectionEngine.pageTitle": "检测引擎",
"xpack.securitySolution.detectionEngine.panelSubtitleShowing": "正在显示",
"xpack.securitySolution.detectionEngine.queryPreview.queryGraphCountLabel": "计数",
- "xpack.securitySolution.detectionEngine.queryPreview.queryGraphDisclaimer": "注意:此预览不包括规则例外和时间戳覆盖的影响。",
- "xpack.securitySolution.detectionEngine.queryPreview.queryGraphDisclaimerEql": "注意:此预览不包括规则例外和时间戳覆盖的影响,且仅显示 100 个结果。",
- "xpack.securitySolution.detectionEngine.queryPreview.queryGraphHitsTitle": "命中数",
"xpack.securitySolution.detectionEngine.queryPreview.queryGraphPreviewError": "提取预览时出错",
"xpack.securitySolution.detectionEngine.queryPreview.queryGraphPreviewInspectTitle": "查询预览",
"xpack.securitySolution.detectionEngine.queryPreview.queryGraphPreviewNoiseWarning": "噪音警告:此规则可能会导致大量噪音。考虑缩小您的查询范围。这基于每小时 1 条告警的线性级数。",
diff --git a/x-pack/test/detection_engine_api_integration/utils.ts b/x-pack/test/detection_engine_api_integration/utils.ts
index ebf3a7008cd57..de66002343212 100644
--- a/x-pack/test/detection_engine_api_integration/utils.ts
+++ b/x-pack/test/detection_engine_api_integration/utils.ts
@@ -116,12 +116,12 @@ export const getSimpleRule = (ruleId = 'rule-1', enabled = false): QueryCreateSc
/**
* This is a typical simple preview rule for testing that is easy for most basic testing
* @param ruleId
- * @param enabled The number of times the rule will be run through the executors. Defaulted to 20,
+ * @param enabled The number of times the rule will be run through the executors. Defaulted to 12,
* the execution time for the default interval time of 5m.
*/
export const getSimplePreviewRule = (
ruleId = 'preview-rule-1',
- invocationCount = 20
+ invocationCount = 12
): PreviewRulesSchema => ({
name: 'Simple Rule Query',
description: 'Simple Rule Query',
From ce2f6171c10d8a351433b27e158b9a1ecb89da04 Mon Sep 17 00:00:00 2001
From: Frank Hassanabad
Date: Mon, 11 Apr 2022 13:41:09 -0600
Subject: [PATCH 21/75] [Security Solutions] Removes POC transforms (#129673)
## Summary
Removes the `metrics_entities` plugin and POC. As a different direction will be taken and people can look back at the git history for it as they see fit if they need to refer to it. Once it's re-added it it will be through an RFC process and re-discussed.
Earlier PR's which added the POC:
https://github.com/elastic/kibana/pull/96446
https://github.com/elastic/kibana/pull/104559
### Checklist
- [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
---
.eslintrc.js | 126 -------
.github/CODEOWNERS | 1 -
docs/developer/plugin-list.asciidoc | 6 -
.../src/get_server_watch_paths.test.ts | 1 -
.../src/get_server_watch_paths.ts | 1 -
x-pack/.i18nrc.json | 1 -
x-pack/plugins/metrics_entities/README.md | 322 ------------------
.../metrics_entities/common/constants.ts | 21 --
.../plugins/metrics_entities/common/index.ts | 13 -
x-pack/plugins/metrics_entities/kibana.json | 14 -
.../server/error_with_status_code.ts | 17 -
.../plugins/metrics_entities/server/index.ts | 28 --
.../metrics_entities/server/modules/README.md | 4 -
.../modules/host_entities/host_entities.json | 38 ---
.../host_entities/host_entities_mapping.json | 45 ---
.../server/modules/host_entities/index.ts | 10 -
.../modules/host_metrics/host_metrics.json | 21 --
.../host_metrics/host_metrics_mapping.json | 83 -----
.../server/modules/host_metrics/index.ts | 11 -
.../metrics_entities/server/modules/index.ts | 71 ----
...destination_country_iso_code_entities.json | 51 ---
...ion_country_iso_code_entities_mapping.json | 120 -------
.../destination_ip_entities.json | 46 ---
.../destination_ip_entities_mapping.json | 84 -----
.../server/modules/network_entities/index.ts | 26 --
.../source_country_iso_code_entities.json | 51 ---
...rce_country_iso_code_entities_mapping.json | 120 -------
.../network_entities/source_ip_entities.json | 46 ---
.../source_ip_entities_mapping.json | 84 -----
.../server/modules/network_metrics/index.ts | 11 -
.../modules/network_metrics/ip_metrics.json | 116 -------
.../network_metrics/ip_metrics_mapping.json | 92 -----
.../metrics_entities/server/modules/types.ts | 38 ---
.../server/modules/user_entities/index.ts | 10 -
.../modules/user_entities/user_entities.json | 51 ---
.../user_entities/user_entities_mapping.json | 53 ---
.../server/modules/user_metrics/index.ts | 11 -
.../modules/user_metrics/user_metrics.json | 56 ---
.../user_metrics/user_metrics_mapping.json | 46 ---
.../plugins/metrics_entities/server/plugin.ts | 90 -----
.../server/routes/delete_transforms.ts | 54 ---
.../server/routes/get_transforms.ts | 36 --
.../metrics_entities/server/routes/index.ts | 10 -
.../server/routes/post_transforms.ts | 96 ------
.../utils/get_metrics_entities_client.ts | 21 --
.../server/routes/utils/index.ts | 8 -
.../server/scripts/check_env_variables.sh | 32 --
.../server/scripts/delete_examples/all.json | 11 -
.../delete_examples/all_prefix_auditbeat.json | 11 -
.../network_entities_auditbeat.json | 3 -
.../scripts/delete_examples/one_module.json | 3 -
.../scripts/delete_examples/two_modules.json | 3 -
.../server/scripts/delete_transforms.sh | 23 --
.../server/scripts/get_transforms.sh | 16 -
.../server/scripts/hard_reset.sh | 17 -
.../server/scripts/post_examples/all.json | 32 --
.../scripts/post_examples/all_auditbeat.json | 23 --
.../network_entities_auditbeat.json | 4 -
.../one_module_allindices_autostart.json | 24 --
.../post_examples/one_module_auditbeat.json | 16 -
.../post_examples/one_module_auto_start.json | 8 -
.../one_module_prefix_auditbeat.json | 5 -
.../post_examples/two_modules_all.json | 24 --
.../post_examples/two_modules_auditbeat.json | 4 -
.../server/scripts/post_transforms.sh | 24 --
.../server/scripts/update_transforms.sh | 13 -
.../server/services/delete_transforms.ts | 38 ---
.../server/services/get_transforms.ts | 24 --
.../metrics_entities/server/services/index.ts | 15 -
.../server/services/install_mappings.ts | 82 -----
.../server/services/install_transforms.ts | 122 -------
.../services/metrics_entities_client.ts | 76 -----
.../services/metrics_entities_client_types.ts | 41 ---
.../server/services/post_transforms.ts | 72 ----
.../server/services/stop_transforms.ts | 8 -
.../server/services/uninstall_mappings.ts | 55 ---
.../server/services/uninstall_transforms.ts | 93 -----
.../services/utils/compute_mapping_index.ts | 24 --
.../services/utils/compute_transform_id.ts | 33 --
.../server/services/utils/get_index_exists.ts | 38 ---
.../server/services/utils/get_json.ts | 10 -
.../services/utils/get_transform_exists.ts | 27 --
.../server/services/utils/index.ts | 17 -
.../services/utils/log_mapping_debug.ts | 20 --
.../services/utils/log_mapping_error.ts | 27 --
.../server/services/utils/log_mapping_info.ts | 20 --
.../services/utils/log_transform_debug.ts | 20 --
.../services/utils/log_transform_error.ts | 27 --
.../services/utils/log_transform_info.ts | 20 --
.../plugins/metrics_entities/server/types.ts | 36 --
x-pack/plugins/metrics_entities/tsconfig.json | 26 --
.../security_solution/common/constants.ts | 42 ---
.../common/experimental_features.ts | 1 -
.../security_solution/hosts/index.ts | 1 -
.../hosts/kpi/authentications/index.ts | 2 -
.../security_solution/hosts/kpi/index.ts | 3 -
.../security_solution/index.ts | 4 +-
.../matrix_histogram/index.ts | 3 -
.../security_solution/network/index.ts | 2 -
.../security_solution/network/kpi/index.ts | 4 -
.../users/authentications/index.ts | 4 -
.../security_solution/users/index.ts | 1 -
.../common/transforms/types.ts | 39 ---
.../containers/authentications/index.tsx | 24 +-
.../containers/matrix_histogram/index.ts | 60 +---
.../use_search_strategy/index.test.ts | 6 -
.../containers/use_search_strategy/index.tsx | 27 +-
.../common/lib/kibana/kibana_react.mock.ts | 4 -
.../detections/components/user_info/index.tsx | 10 -
.../public/hosts/containers/hosts/index.tsx | 21 +-
.../kpi_hosts/authentications/index.tsx | 24 +-
.../containers/kpi_hosts/hosts/index.tsx | 18 +-
.../containers/kpi_hosts/unique_ips/index.tsx | 24 +-
.../containers/kpi_network/dns/index.tsx | 19 +-
.../kpi_network/network_events/index.tsx | 18 +-
.../kpi_network/tls_handshakes/index.tsx | 19 +-
.../kpi_network/unique_private_ips/index.tsx | 19 +-
.../network_top_countries/index.tsx | 36 +-
.../containers/network_top_n_flow/index.tsx | 35 +-
.../risk_score/containers/all/index.tsx | 13 +-
.../public/transforms/containers/api.ts | 49 ---
.../transforms/containers/translations.ts | 15 -
.../containers/use_create_transforms.ts | 112 ------
.../transforms/containers/use_transforms.ts | 111 ------
.../public/transforms/jest.config.js | 26 --
.../transforms/utils/adjust_timerange.test.ts | 71 ----
.../transforms/utils/adjust_timerange.ts | 40 ---
.../utils/create_indices_from_prefix.test.ts | 31 --
.../utils/create_indices_from_prefix.ts | 25 --
.../utils/get_settings_match.test.ts | 82 -----
.../transforms/utils/get_settings_match.ts | 34 --
.../utils/get_transform_changes.test.ts | 177 ----------
.../transforms/utils/get_transform_changes.ts | 54 ---
.../get_transform_changes_for_hosts.test.ts | 36 --
.../utils/get_transform_changes_for_hosts.ts | 37 --
.../get_transform_changes_for_kpi.test.ts | 61 ----
.../utils/get_transform_changes_for_kpi.ts | 51 ---
...sform_changes_for_matrix_histogram.test.ts | 45 ---
..._transform_changes_for_matrix_histogram.ts | 51 ---
.../get_transform_changes_for_network.test.ts | 97 ------
.../get_transform_changes_for_network.ts | 82 -----
.../get_transform_changes_for_users.test.ts | 36 --
.../utils/get_transform_changes_for_users.ts | 37 --
...et_transform_changes_if_they_exist.test.ts | 305 -----------------
.../get_transform_changes_if_they_exist.ts | 55 ---
.../public/transforms/utils/index.ts | 17 -
.../utils/is_filter_query_compatible.test.ts | 87 -----
.../utils/is_filter_query_compatible.ts | 54 ---
.../utils/transform_config_schema.mock.ts | 43 ---
.../public/transforms/utils/types.ts | 50 ---
.../factory/hosts/all/index.ts | 41 ---
.../hosts/all/query.all_hosts_entities.dsl.ts | 92 -----
.../factory/hosts/index.test.ts | 9 +-
.../security_solution/factory/hosts/index.ts | 12 +-
.../hosts/kpi/authentications/helpers.ts | 10 -
.../hosts/kpi/authentications/index.ts | 52 +--
....hosts_kpi_authentications_entities.dsl.ts | 83 -----
.../factory/hosts/kpi/hosts/index.ts | 25 --
.../query.hosts_kpi_hosts_entities.dsl.ts | 65 ----
.../factory/hosts/kpi/unique_ips/index.ts | 39 ---
...query.hosts_kpi_unique_ips_entities.dsl.ts | 83 -----
.../matrix_histogram/authentications/index.ts | 9 -
....authentications_histogram_entities.dsl.ts | 77 -----
.../factory/matrix_histogram/helpers.ts | 16 -
.../factory/matrix_histogram/index.ts | 10 +-
.../factory/network/index.test.ts | 15 +-
.../factory/network/index.ts | 21 +-
.../factory/network/kpi/dns/index.ts | 19 --
.../dns/query.network_kip_dns_entities.dsl.ts | 52 ---
.../factory/network/kpi/index.ts | 15 +-
.../network/kpi/network_events/index.ts | 22 --
...network_kpi_network_events_entities.dsl.ts | 52 ---
.../network/kpi/tls_handshakes/index.ts | 22 --
...network_kpi_tls_handshakes_entities.dsl.ts | 52 ---
.../network/kpi/unique_private_ips/index.ts | 46 ---
...ork_kpi_unique_private_ips_entities.dsl.ts | 106 ------
.../factory/network/top_countries/index.ts | 39 ---
...uery.top_countries_network_entities.dsl.ts | 162 ---------
.../factory/network/top_n_flow/index.ts | 36 --
.../query.top_n_flow_network_entities.dsl.ts | 165 ---------
.../authentications/dsl/query_entities.dsl.ts | 81 -----
.../factory/users/authentications/helpers.ts | 65 ----
.../factory/users/authentications/index.tsx | 51 +--
.../security_solution/factory/users/index.ts | 3 +-
.../security_solution/server/ui_settings.ts | 23 --
.../translations/translations/fr-FR.json | 3 -
.../translations/translations/ja-JP.json | 3 -
.../translations/translations/zh-CN.json | 3 -
x-pack/test/tsconfig.json | 1 -
189 files changed, 117 insertions(+), 7545 deletions(-)
delete mode 100755 x-pack/plugins/metrics_entities/README.md
delete mode 100644 x-pack/plugins/metrics_entities/common/constants.ts
delete mode 100644 x-pack/plugins/metrics_entities/common/index.ts
delete mode 100644 x-pack/plugins/metrics_entities/kibana.json
delete mode 100644 x-pack/plugins/metrics_entities/server/error_with_status_code.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/index.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/README.md
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/host_entities/host_entities.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/host_entities/host_entities_mapping.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/host_entities/index.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/host_metrics/host_metrics.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/host_metrics/host_metrics_mapping.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/host_metrics/index.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/index.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/network_entities/destination_country_iso_code_entities.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/network_entities/destination_country_iso_code_entities_mapping.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/network_entities/destination_ip_entities.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/network_entities/destination_ip_entities_mapping.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/network_entities/index.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/network_entities/source_country_iso_code_entities.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/network_entities/source_country_iso_code_entities_mapping.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/network_entities/source_ip_entities.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/network_entities/source_ip_entities_mapping.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/network_metrics/index.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/network_metrics/ip_metrics.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/network_metrics/ip_metrics_mapping.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/types.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/user_entities/index.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/user_entities/user_entities.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/user_entities/user_entities_mapping.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/user_metrics/index.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/user_metrics/user_metrics.json
delete mode 100644 x-pack/plugins/metrics_entities/server/modules/user_metrics/user_metrics_mapping.json
delete mode 100644 x-pack/plugins/metrics_entities/server/plugin.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/routes/delete_transforms.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/routes/get_transforms.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/routes/index.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/routes/post_transforms.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/routes/utils/get_metrics_entities_client.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/routes/utils/index.ts
delete mode 100755 x-pack/plugins/metrics_entities/server/scripts/check_env_variables.sh
delete mode 100644 x-pack/plugins/metrics_entities/server/scripts/delete_examples/all.json
delete mode 100644 x-pack/plugins/metrics_entities/server/scripts/delete_examples/all_prefix_auditbeat.json
delete mode 100644 x-pack/plugins/metrics_entities/server/scripts/delete_examples/network_entities_auditbeat.json
delete mode 100644 x-pack/plugins/metrics_entities/server/scripts/delete_examples/one_module.json
delete mode 100644 x-pack/plugins/metrics_entities/server/scripts/delete_examples/two_modules.json
delete mode 100755 x-pack/plugins/metrics_entities/server/scripts/delete_transforms.sh
delete mode 100755 x-pack/plugins/metrics_entities/server/scripts/get_transforms.sh
delete mode 100755 x-pack/plugins/metrics_entities/server/scripts/hard_reset.sh
delete mode 100644 x-pack/plugins/metrics_entities/server/scripts/post_examples/all.json
delete mode 100644 x-pack/plugins/metrics_entities/server/scripts/post_examples/all_auditbeat.json
delete mode 100644 x-pack/plugins/metrics_entities/server/scripts/post_examples/network_entities_auditbeat.json
delete mode 100644 x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_allindices_autostart.json
delete mode 100644 x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_auditbeat.json
delete mode 100644 x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_auto_start.json
delete mode 100644 x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_prefix_auditbeat.json
delete mode 100644 x-pack/plugins/metrics_entities/server/scripts/post_examples/two_modules_all.json
delete mode 100644 x-pack/plugins/metrics_entities/server/scripts/post_examples/two_modules_auditbeat.json
delete mode 100755 x-pack/plugins/metrics_entities/server/scripts/post_transforms.sh
delete mode 100755 x-pack/plugins/metrics_entities/server/scripts/update_transforms.sh
delete mode 100644 x-pack/plugins/metrics_entities/server/services/delete_transforms.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/get_transforms.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/index.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/install_mappings.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/install_transforms.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/metrics_entities_client.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/metrics_entities_client_types.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/post_transforms.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/stop_transforms.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/uninstall_mappings.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/uninstall_transforms.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/utils/compute_mapping_index.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/utils/compute_transform_id.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/utils/get_index_exists.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/utils/get_json.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/utils/get_transform_exists.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/utils/index.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/utils/log_mapping_debug.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/utils/log_mapping_error.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/utils/log_mapping_info.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/utils/log_transform_debug.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/utils/log_transform_error.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/services/utils/log_transform_info.ts
delete mode 100644 x-pack/plugins/metrics_entities/server/types.ts
delete mode 100644 x-pack/plugins/metrics_entities/tsconfig.json
delete mode 100644 x-pack/plugins/security_solution/common/transforms/types.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/containers/api.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/containers/translations.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/containers/use_create_transforms.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/containers/use_transforms.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/jest.config.js
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/adjust_timerange.test.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/adjust_timerange.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/create_indices_from_prefix.test.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/create_indices_from_prefix.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_settings_match.test.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_settings_match.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes.test.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_hosts.test.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_hosts.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_kpi.test.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_kpi.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_matrix_histogram.test.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_matrix_histogram.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_network.test.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_network.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_users.test.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_users.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_if_they_exist.test.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_if_they_exist.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/index.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/is_filter_query_compatible.test.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/is_filter_query_compatible.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/transform_config_schema.mock.ts
delete mode 100644 x-pack/plugins/security_solution/public/transforms/utils/types.ts
delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/query.all_hosts_entities.dsl.ts
delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/authentications/query.hosts_kpi_authentications_entities.dsl.ts
delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/query.hosts_kpi_hosts_entities.dsl.ts
delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/query.hosts_kpi_unique_ips_entities.dsl.ts
delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/query.authentications_histogram_entities.dsl.ts
delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/query.network_kip_dns_entities.dsl.ts
delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/query.network_kpi_network_events_entities.dsl.ts
delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/query.network_kpi_tls_handshakes_entities.dsl.ts
delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/query.network_kpi_unique_private_ips_entities.dsl.ts
delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/query.top_countries_network_entities.dsl.ts
delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/query.top_n_flow_network_entities.dsl.ts
delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/dsl/query_entities.dsl.ts
diff --git a/.eslintrc.js b/.eslintrc.js
index b12dc63066370..08af34d24e7f5 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1242,132 +1242,6 @@ module.exports = {
},
},
- /**
- * Metrics entities overrides. These rules below are maintained and owned by
- * the people within the security-solution-platform team. Please see ping them
- * or check with them if you are encountering issues, have suggestions, or would
- * like to add, change, or remove any particular rule. Linters, Typescript, and rules
- * evolve and change over time just like coding styles, so please do not hesitate to
- * reach out.
- */
- {
- // front end and common typescript and javascript files only
- files: [
- 'x-pack/plugins/metrics_entities/public/**/*.{js,mjs,ts,tsx}',
- 'x-pack/plugins/metrics_entities/common/**/*.{js,mjs,ts,tsx}',
- ],
- rules: {
- 'import/no-nodejs-modules': 'error',
- 'no-restricted-imports': [
- 'error',
- {
- // prevents UI code from importing server side code and then webpack including it when doing builds
- patterns: ['**/server/*'],
- },
- ],
- },
- },
- {
- // typescript and javascript for front and back end
- files: ['x-pack/plugins/metrics_entities/**/*.{js,mjs,ts,tsx}'],
- plugins: ['eslint-plugin-node'],
- env: {
- jest: true,
- },
- rules: {
- 'accessor-pairs': 'error',
- 'array-callback-return': 'error',
- 'no-array-constructor': 'error',
- complexity: 'error',
- 'consistent-return': 'error',
- 'func-style': ['error', 'expression'],
- 'import/order': [
- 'error',
- {
- groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
- 'newlines-between': 'always',
- },
- ],
- 'sort-imports': [
- 'error',
- {
- ignoreDeclarationSort: true,
- },
- ],
- 'node/no-deprecated-api': 'error',
- 'no-bitwise': 'error',
- 'no-continue': 'error',
- 'no-dupe-keys': 'error',
- 'no-duplicate-case': 'error',
- 'no-duplicate-imports': 'error',
- 'no-empty-character-class': 'error',
- 'no-empty-pattern': 'error',
- 'no-ex-assign': 'error',
- 'no-extend-native': 'error',
- 'no-extra-bind': 'error',
- 'no-extra-boolean-cast': 'error',
- 'no-extra-label': 'error',
- 'no-func-assign': 'error',
- 'no-implicit-globals': 'error',
- 'no-implied-eval': 'error',
- 'no-invalid-regexp': 'error',
- 'no-inner-declarations': 'error',
- 'no-lone-blocks': 'error',
- 'no-multi-assign': 'error',
- 'no-misleading-character-class': 'error',
- 'no-new-symbol': 'error',
- 'no-obj-calls': 'error',
- 'no-param-reassign': ['error', { props: true }],
- 'no-process-exit': 'error',
- 'no-prototype-builtins': 'error',
- 'no-return-await': 'error',
- 'no-self-compare': 'error',
- 'no-shadow-restricted-names': 'error',
- 'no-sparse-arrays': 'error',
- 'no-this-before-super': 'error',
- // rely on typescript
- 'no-undef': 'off',
- 'no-unreachable': 'error',
- 'no-unsafe-finally': 'error',
- 'no-useless-call': 'error',
- 'no-useless-catch': 'error',
- 'no-useless-concat': 'error',
- 'no-useless-computed-key': 'error',
- 'no-useless-escape': 'error',
- 'no-useless-rename': 'error',
- 'no-useless-return': 'error',
- 'no-void': 'error',
- 'one-var-declaration-per-line': 'error',
- 'prefer-object-spread': 'error',
- 'prefer-promise-reject-errors': 'error',
- 'prefer-rest-params': 'error',
- 'prefer-spread': 'error',
- 'prefer-template': 'error',
- 'require-atomic-updates': 'error',
- 'symbol-description': 'error',
- 'vars-on-top': 'error',
- '@typescript-eslint/explicit-member-accessibility': 'error',
- '@typescript-eslint/no-this-alias': 'error',
- '@typescript-eslint/no-explicit-any': 'error',
- '@typescript-eslint/no-useless-constructor': 'error',
- '@typescript-eslint/unified-signatures': 'error',
- '@typescript-eslint/explicit-function-return-type': 'error',
- '@typescript-eslint/no-non-null-assertion': 'error',
- '@typescript-eslint/no-unused-vars': 'error',
- 'no-template-curly-in-string': 'error',
- 'sort-keys': 'error',
- 'prefer-destructuring': 'error',
- 'no-restricted-imports': [
- 'error',
- {
- // prevents code from importing files that contain the name "legacy" within their name. This is a mechanism
- // to help deprecation and prevent accidental re-use/continued use of code we plan on removing. If you are
- // finding yourself turning this off a lot for "new code" consider renaming the file and functions if it has valid uses.
- patterns: ['*legacy*'],
- },
- ],
- },
- },
/**
* Alerting Services overrides
*/
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 3c991e6a61d53..b846bc0801870 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -394,7 +394,6 @@
/x-pack/test/plugin_functional/plugins/resolver_test/ @elastic/security-solution
/x-pack/test/plugin_functional/test_suites/resolver/ @elastic/security-solution
/x-pack/plugins/security_solution/ @elastic/security-solution
-/x-pack/plugins/metrics_entities/ @elastic/security-solution
/x-pack/test/detection_engine_api_integration @elastic/security-solution
/x-pack/test/lists_api_integration @elastic/security-solution
/x-pack/test/api_integration/apis/security_solution @elastic/security-solution
diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc
index 04b21bf737815..e96f1cd819186 100644
--- a/docs/developer/plugin-list.asciidoc
+++ b/docs/developer/plugin-list.asciidoc
@@ -524,12 +524,6 @@ using the CURL scripts in the scripts folder.
|Visualize geo data from Elasticsearch or 3rd party geo-services.
-|{kib-repo}blob/{branch}/x-pack/plugins/metrics_entities/README.md[metricsEntities]
-|This is the metrics and entities plugin where you add can add transforms for your project
-and group those transforms into modules. You can also re-use existing transforms in your
-newly created modules as well.
-
-
|{kib-repo}blob/{branch}/x-pack/plugins/ml/readme.md[ml]
|This plugin provides access to the machine learning features provided by
Elastic.
diff --git a/packages/kbn-cli-dev-mode/src/get_server_watch_paths.test.ts b/packages/kbn-cli-dev-mode/src/get_server_watch_paths.test.ts
index 25bc59bf78458..12074bf493218 100644
--- a/packages/kbn-cli-dev-mode/src/get_server_watch_paths.test.ts
+++ b/packages/kbn-cli-dev-mode/src/get_server_watch_paths.test.ts
@@ -76,7 +76,6 @@ it('produces the right watch and ignore list', () => {
/x-pack/plugins/lists/server/scripts,
/x-pack/plugins/security_solution/scripts,
/x-pack/plugins/security_solution/server/lib/detection_engine/scripts,
- /x-pack/plugins/metrics_entities/server/scripts,
/x-pack/plugins/uptime/e2e,
]
`);
diff --git a/packages/kbn-cli-dev-mode/src/get_server_watch_paths.ts b/packages/kbn-cli-dev-mode/src/get_server_watch_paths.ts
index acfc9aeecdc80..8f2363b398d6e 100644
--- a/packages/kbn-cli-dev-mode/src/get_server_watch_paths.ts
+++ b/packages/kbn-cli-dev-mode/src/get_server_watch_paths.ts
@@ -66,7 +66,6 @@ export function getServerWatchPaths({ pluginPaths, pluginScanDirs }: Options) {
fromRoot('x-pack/plugins/lists/server/scripts'),
fromRoot('x-pack/plugins/security_solution/scripts'),
fromRoot('x-pack/plugins/security_solution/server/lib/detection_engine/scripts'),
- fromRoot('x-pack/plugins/metrics_entities/server/scripts'),
fromRoot('x-pack/plugins/uptime/e2e'),
];
diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json
index fe2f3dea0017a..3960cdd76a761 100644
--- a/x-pack/.i18nrc.json
+++ b/x-pack/.i18nrc.json
@@ -38,7 +38,6 @@
"xpack.logstash": ["plugins/logstash"],
"xpack.main": "legacy/plugins/xpack_main",
"xpack.maps": ["plugins/maps"],
- "xpack.metricsEntities": "plugins/metrics_entities",
"xpack.ml": ["plugins/ml"],
"xpack.monitoring": ["plugins/monitoring"],
"xpack.osquery": ["plugins/osquery"],
diff --git a/x-pack/plugins/metrics_entities/README.md b/x-pack/plugins/metrics_entities/README.md
deleted file mode 100755
index 71ac2730f3831..0000000000000
--- a/x-pack/plugins/metrics_entities/README.md
+++ /dev/null
@@ -1,322 +0,0 @@
-# metrics_entities
-
-This is the metrics and entities plugin where you add can add transforms for your project
-and group those transforms into modules. You can also re-use existing transforms in your
-newly created modules as well.
-
-## Turn on experimental flags
-During at least phase 1 of this development, please add these to your `kibana.dev.yml` file to turn on the feature:
-
-```ts
-xpack.metricsEntities.enabled: true
-xpack.securitySolution.enableExperimental: ['metricsEntitiesEnabled']
-```
-
-## Quick start on using scripts to call the API
-
-The scripts rely on CURL and jq:
-
-- [CURL](https://curl.haxx.se)
-- [jq](https://stedolan.github.io/jq/)
-
-Install curl and jq
-
-```sh
-brew update
-brew install curl
-brew install jq
-```
-
-Open `$HOME/.zshrc` or `${HOME}.bashrc` depending on your SHELL output from `echo $SHELL`
-and add these environment variables:
-
-```sh
-export ELASTICSEARCH_USERNAME=${user}
-export ELASTICSEARCH_PASSWORD=${password}
-export ELASTICSEARCH_URL=https://${ip}:9200
-export KIBANA_URL=http://localhost:5601
-```
-
-source `$HOME/.zshrc` or `${HOME}.bashrc` to ensure variables are set:
-
-```sh
-source ~/.zshrc
-```
-
-Restart Kibana and ensure that you are using `--no-base-path` as changing the base path is a feature but will
-get in the way of the CURL scripts written as is.
-
-Go to the scripts folder `cd kibana/x-pack/plugins/metrics_entities/server/scripts` and can run some of the scripts
-such as:
-
-```sh
-./post_transforms.sh ./post_examples/all.json
-```
-
-which will post transforms from the `all.json`
-
-You can also delete them by running:
-
-```sh
-./delete_transforms.sh ./delete_examples/all.json
-```
-
-See the folder for other curl scripts that exercise parts of the REST API and feel free to add your own examples
-in the folder as well.
-
-## Quick start on how to add a transform
-
-You will want to figure out how you want your transform from within Kibana roughly using
-the UI and then copy the JSON. The JSON you will want to change and paste within a folder
-which represents a module.
-
-For example, for the `host_entities` and a `host_entities_mapping` we created a folder called host_entities
-here:
-
-```sh
-sever/modules/host_entities
-```
-
-Then we add two files, a subset of the transform JSON and a mapping like so:
-
-```sh
-server/modules/host_entities/host_entities_mapping.json <--- this is the mappings
-server/modules/host_entities/host_entities.json <--- This is a subset of the transform JSON
-index.ts <--- Import/export your json here
-```
-
-The mappings can be normal mapping like so with `host_entities_mapping.json`:
-```json
-{
- "mappings": {
- "_meta": {
- "index": "host_ent"
- },
- "dynamic": "strict",
- "properties": {
- "@timestamp": {
- "type": "date"
- },
- "metrics": {
- "properties": {
- "host": {
- "properties": {
- "name": {
- "properties": {
- "value_count": {
- "type": "long"
- }
- }
- }
- }
- }
- }
- },
- "host": {
- "properties": {
- "name": {
- "type": "keyword"
- },
- "os": {
- "properties": {
- "name": {
- "type": "keyword"
- },
- "version": {
- "type": "keyword"
- }
- }
- }
- }
- }
- }
- }
-}
-```
-
-One caveat is that you need to add this to the meta section to tell it what the name will be:
-```json
- "_meta": {
- "index": "host_ent"
- },
-```
-
-Keep the name short as there is only 65 characters for a transform job and we prepend extra information to the mapping such as:
-* prefix
-* name of estc
-
-Although not required, a `"dynamic": "strict"` is strongly encouraged to prevent mapping guesses from elastic and it will be better for us
-to spot errors quicker in the mappings such as type-o's if this is set to strict.
-
-Next, for the transform, you should add a subset that doesn't have any additional settings or meta associated like so for `host_entities.json`:
-
-```json
-{
- "id": "host_ent",
- "description": "[host.name entities] grouped by @timestamp, host.name, os.name, and os.version, and aggregated on host.name",
- "pivot": {
- "group_by": {
- "@timestamp": {
- "date_histogram": {
- "field": "@timestamp",
- "calendar_interval": "1h"
- }
- },
- "host.name": {
- "terms": {
- "field": "host.name"
- }
- },
- "host.os.name": {
- "terms": {
- "field": "host.os.name",
- "missing_bucket": true
- }
- },
- "host.os.version": {
- "terms": {
- "field": "host.os.version",
- "missing_bucket": true
- }
- }
- },
- "aggregations": {
- "metrics.host.name.value_count": {
- "value_count": {
- "field": "host.name"
- }
- }
- }
- }
-}
-```
-
-Look in the `server/modules` for other examples, but it should be that clear cut. The final part is to wire everything up in the code by touching a few files
-to either add this to an existing module or create your own module. In `server/module/host_entities` we add an `index.ts` like so that does an import/export
-of the JSON:
-
-```sh
-import hostEntities from './host_entities.json';
-import hostEntitiesMapping from './host_entities_mapping.json';
-export { hostEntities, hostEntitiesMapping };
-```
-
-Then in `modules/index.ts` we add a new module name if we are creating a new module to the `export enum ModuleNames {` like so:
-
-```ts
-// Import your host entities you just made
-import { hostEntities, hostEntitiesMapping } from './host_entities';
-
-/**
- * These module names will map 1 to 1 to the REST interface.
- */
-export enum ModuleNames {
- hostSummaryMetrics = 'host_metrics',
- hostSummaryEntities = 'host_entities', // <-- Add the entities/transform and give it a enum name and a module name
- networkSummaryEntities = 'network_entities',
- networkSummaryMetrics = 'network_metrics',
- userSummaryEntities = 'user_entities',
- userSummaryMetrics = 'user_metrics',
-}
-```
-
-If you're not creating a new module but rather you are adding to an existing module, you can skip the above step. Next, you
-just need to add your installable transform and installable mapping to the two data structures of `installableTransforms` and
-`installableMappings` like so:
-
-```ts
-/**
- * Add any new folders as modules with their names below and grouped with
- * key values.
- */
-export const installableTransforms: Record = {
- [ModuleNames.hostSummaryMetrics]: [hostMetrics],
- [ModuleNames.hostSummaryEntities]: [hostEntities], // <-- Adds my new module name and transform to a new array.
- [ModuleNames.networkSummaryEntities]: [
- destinationIpEntities, // <-- If instead I am adding to an existing module, I just add it to the array like these show
- sourceIpEntities,
- destinationCountryIsoCodeEntities,
- sourceCountryIsoCodeEntities,
- ],
- [ModuleNames.networkSummaryMetrics]: [ipMetrics],
- [ModuleNames.userSummaryEntities]: [userEntities],
- [ModuleNames.userSummaryMetrics]: [userMetrics],
-};
-
-/**
- * For all the mapping types, add each with their names below and grouped with
- * key values.
- */
-export const installableMappings: Record = {
- [ModuleNames.hostSummaryMetrics]: [hostMetricsMapping],
- [ModuleNames.hostSummaryEntities]: [hostEntitiesMapping], // <-- Adds my new module name and mapping to a new array.
- [ModuleNames.networkSummaryEntities]: [ // <-- If instead I am adding to an existing module, I just add it to the array like these show
- sourceIpEntitiesMapping,
- destinationIpEntitiesMapping,
- destinationCountryIsoCodeEntitiesMapping,
- sourceCountryIsoCodeEntitiesMapping,
- ],
- [ModuleNames.networkSummaryMetrics]: [ipMetricsMapping],
- [ModuleNames.userSummaryEntities]: [userEntitiesMapping],
- [ModuleNames.userSummaryMetrics]: [userMetricsMapping],
-};
-```
-
-And after that, you should check out if there are any existing e2e tests or unit tests to update here to ensure that your mapping and transform will
-pass ci. Create a pull request and your mapping and transform are completed.
-
-To call into the code to activate your module and create your transforms and mappings would be the following where you substitute your
-${KIBANA_URL} with your kibana URL and the ${SPACE_URL} with any space id you have. If you're using the default space then you would use
-an empty string:
-```json
-POST ${KIBANA_URL}${SPACE_URL}/api/metrics_entities/transforms
-{
- "prefix": "all",
- "modules": [
- "host_entities",
- ],
- "indices": [
- "auditbeat-*",
- "endgame-*",
- "filebeat-*",
- "logs-*",
- "packetbeat-*",
- "winlogbeat-*",
- "-*elastic-cloud-logs-*"
- ],
- "auto_start": true,
- "settings": {
- "max_page_search_size": 5000
- },
- "query": {
- "range": {
- "@timestamp": {
- "gte": "now-1d/d",
- "format": "strict_date_optional_time"
- }
- }
- }
-}
-```
-
-Very similar to the regular transform REST API, with the caveats that you define which modules you want to install, the prefix name you want to use, and
-if you want to `auto_start` it or not. The rest such as `settings`, `query` will be the same as the transforms API. They will also push those same setting into
-each of your transforms within your module(s) as the same setting for each individual ones.
-
-## TODO List
-During the phase 1, phase 2, phase N, this TODO will exist as a reminder and notes for what still needs to be developed. These are not in a priority order, but
-are notes during the phased approach. As we approach production and the feature flags are removed these TODO's should be removed in favor of Kibana issues or regular
-left over TODO's in the code base.
-
-- Add these properties to the route which are:
- - disable_transforms/exclude flag to exclude 1 or more transforms within a module
- - pipeline flag
- - Change the REST routes on post to change the indexes for whichever indexes you want
-- Unit tests to ensure the data of the mapping.json includes the correct fields such as _meta, at least one alias, a mapping section, etc...
-- Add text/keyword and other things to the mappings (not just keyword maybe?) ... At least review the mappings one more time
-- Add a sort of @timestamp to the output destination indexes?
-- Add the REST Kibana security based tags if needed and push those to any plugins using this plugin. Something like: tags: ['access:metricsEntities-read'] and ['access:metricsEntities-all'],
-- Add schema validation choosing some schema library (io-ts or Kibana Schema or ... )
-- Add unit tests
-- Add e2e tests
-- Any UI code should not end up here. There is none right now, but all UI code should be within a kbn package or security_solutions
diff --git a/x-pack/plugins/metrics_entities/common/constants.ts b/x-pack/plugins/metrics_entities/common/constants.ts
deleted file mode 100644
index 8efa0327f5f41..0000000000000
--- a/x-pack/plugins/metrics_entities/common/constants.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-/**
- * Base route
- */
-export const METRICS_ENTITIES_URL = '/api/metrics_entities';
-
-/**
- * Transforms route
- */
-export const METRICS_ENTITIES_TRANSFORMS = `${METRICS_ENTITIES_URL}/transforms`;
-
-/**
- * Global prefix for all the transform jobs
- */
-export const ELASTIC_NAME = 'estc';
diff --git a/x-pack/plugins/metrics_entities/common/index.ts b/x-pack/plugins/metrics_entities/common/index.ts
deleted file mode 100644
index f100308ef2e9b..0000000000000
--- a/x-pack/plugins/metrics_entities/common/index.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-// Careful of exporting anything from this file as any file(s) you export here will cause your functions to be exposed as public.
-// If you're using functions/types/etc... internally or within integration tests it's best to import directly from their paths
-// than expose the functions/types/etc... here. You should _only_ expose functions/types/etc... that need to be shared with other plugins here.
-// When you do have to add things here you might want to consider creating a package such to share with other plugins instead as packages
-// are easier to break down.
-// See: https://docs.elastic.dev/kibana-dev-docs/key-concepts/platform-intro#public-plugin-api
diff --git a/x-pack/plugins/metrics_entities/kibana.json b/x-pack/plugins/metrics_entities/kibana.json
deleted file mode 100644
index 9d3a4f7f66a8d..0000000000000
--- a/x-pack/plugins/metrics_entities/kibana.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "id": "metricsEntities",
- "owner": {
- "name": "Security solution",
- "githubTeam": "security-solution"
- },
- "version": "8.0.0",
- "kibanaVersion": "kibana",
- "configPath": ["xpack", "metricsEntities"],
- "server": true,
- "ui": false,
- "requiredPlugins": ["data", "dataEnhanced"],
- "optionalPlugins": []
-}
diff --git a/x-pack/plugins/metrics_entities/server/error_with_status_code.ts b/x-pack/plugins/metrics_entities/server/error_with_status_code.ts
deleted file mode 100644
index 15f7797fa424f..0000000000000
--- a/x-pack/plugins/metrics_entities/server/error_with_status_code.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-export class ErrorWithStatusCode extends Error {
- private readonly statusCode: number;
-
- constructor(message: string, statusCode: number) {
- super(message);
- this.statusCode = statusCode;
- }
-
- public getStatusCode = (): number => this.statusCode;
-}
diff --git a/x-pack/plugins/metrics_entities/server/index.ts b/x-pack/plugins/metrics_entities/server/index.ts
deleted file mode 100644
index 15b0d110dd178..0000000000000
--- a/x-pack/plugins/metrics_entities/server/index.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { schema } from '@kbn/config-schema';
-
-import { PluginInitializerContext } from '../../../../src/core/server';
-
-import { MetricsEntitiesPlugin } from './plugin';
-
-// This exports static code and TypeScript types,
-// as well as, Kibana Platform `plugin()` initializer.
-
-export const plugin = (initializerContext: PluginInitializerContext): MetricsEntitiesPlugin => {
- return new MetricsEntitiesPlugin(initializerContext);
-};
-
-export type { MetricsEntitiesPluginSetup, MetricsEntitiesPluginStart } from './types';
-
-export const config = {
- schema: schema.object({
- // This plugin is experimental and should be disabled by default.
- enabled: schema.boolean({ defaultValue: false }),
- }),
-};
diff --git a/x-pack/plugins/metrics_entities/server/modules/README.md b/x-pack/plugins/metrics_entities/server/modules/README.md
deleted file mode 100644
index d4e28a2f83ed0..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Modules
-
-This is where all the module types exist so you can load different bundled modules
-with a REST endpoint.
\ No newline at end of file
diff --git a/x-pack/plugins/metrics_entities/server/modules/host_entities/host_entities.json b/x-pack/plugins/metrics_entities/server/modules/host_entities/host_entities.json
deleted file mode 100644
index ef6bcfc452860..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/host_entities/host_entities.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "id": "host_ent",
- "description": "[host.name entities] grouped by @timestamp, host.name, os.name, and os.version, and aggregated on host.name",
- "pivot": {
- "group_by": {
- "@timestamp": {
- "date_histogram": {
- "field": "@timestamp",
- "calendar_interval": "1h"
- }
- },
- "host.name": {
- "terms": {
- "field": "host.name"
- }
- },
- "host.os.name": {
- "terms": {
- "field": "host.os.name",
- "missing_bucket": true
- }
- },
- "host.os.version": {
- "terms": {
- "field": "host.os.version",
- "missing_bucket": true
- }
- }
- },
- "aggregations": {
- "metrics.host.name.value_count": {
- "value_count": {
- "field": "host.name"
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/host_entities/host_entities_mapping.json b/x-pack/plugins/metrics_entities/server/modules/host_entities/host_entities_mapping.json
deleted file mode 100644
index 1f1e93dabfb5f..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/host_entities/host_entities_mapping.json
+++ /dev/null
@@ -1,45 +0,0 @@
-{
- "mappings": {
- "_meta": {
- "index": "host_ent"
- },
- "dynamic": "strict",
- "properties": {
- "@timestamp": {
- "type": "date"
- },
- "metrics": {
- "properties": {
- "host": {
- "properties": {
- "name": {
- "properties": {
- "value_count": {
- "type": "long"
- }
- }
- }
- }
- }
- }
- },
- "host": {
- "properties": {
- "name": {
- "type": "keyword"
- },
- "os": {
- "properties": {
- "name": {
- "type": "keyword"
- },
- "version": {
- "type": "keyword"
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/host_entities/index.ts b/x-pack/plugins/metrics_entities/server/modules/host_entities/index.ts
deleted file mode 100644
index c3f34cd0f535c..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/host_entities/index.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import hostEntities from './host_entities.json';
-import hostEntitiesMapping from './host_entities_mapping.json';
-export { hostEntities, hostEntitiesMapping };
diff --git a/x-pack/plugins/metrics_entities/server/modules/host_metrics/host_metrics.json b/x-pack/plugins/metrics_entities/server/modules/host_metrics/host_metrics.json
deleted file mode 100644
index 8388721f98926..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/host_metrics/host_metrics.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "id": "host_met",
- "description": "[host.name metrics] grouped by @timestamp and aggregated on host.name",
- "pivot": {
- "group_by": {
- "@timestamp": {
- "date_histogram": {
- "field": "@timestamp",
- "calendar_interval": "1h"
- }
- }
- },
- "aggregations": {
- "metrics.host.name.cardinality": {
- "cardinality": {
- "field": "host.name"
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/host_metrics/host_metrics_mapping.json b/x-pack/plugins/metrics_entities/server/modules/host_metrics/host_metrics_mapping.json
deleted file mode 100644
index 7975fe3c6ed0a..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/host_metrics/host_metrics_mapping.json
+++ /dev/null
@@ -1,83 +0,0 @@
-{
- "mappings": {
- "_meta": {
- "index": "host_met"
- },
- "properties": {
- "metrics": {
- "properties": {
- "source": {
- "properties": {
- "ip": {
- "properties": {
- "value_count": {
- "type": "long"
- },
- "cardinality": {
- "type": "long"
- }
- }
- },
- "bytes": {
- "properties": {
- "sum": {
- "type": "long"
- }
- }
- }
- }
- },
- "destination": {
- "properties": {
- "ip": {
- "properties": {
- "value_count": {
- "type": "long"
- },
- "cardinality": {
- "type": "long"
- }
- }
- },
- "bytes": {
- "properties": {
- "sum": {
- "type": "long"
- }
- }
- }
- }
- },
- "network": {
- "properties": {
- "community_id": {
- "properties": {
- "cardinality": {
- "type": "long"
- }
- }
- }
- }
- },
- "host": {
- "properties": {
- "name": {
- "properties": {
- "value_count": {
- "type": "long"
- },
- "cardinality": {
- "type": "long"
- }
- }
- }
- }
- }
- }
- },
- "@timestamp": {
- "type": "date"
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/host_metrics/index.ts b/x-pack/plugins/metrics_entities/server/modules/host_metrics/index.ts
deleted file mode 100644
index e11c5321ede85..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/host_metrics/index.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import hostMetrics from './host_metrics.json';
-import hostMetricsMapping from './host_metrics_mapping.json';
-
-export { hostMetrics, hostMetricsMapping };
diff --git a/x-pack/plugins/metrics_entities/server/modules/index.ts b/x-pack/plugins/metrics_entities/server/modules/index.ts
deleted file mode 100644
index 61aca783a6c03..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/index.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { hostMetrics, hostMetricsMapping } from './host_metrics';
-import { userMetrics, userMetricsMapping } from './user_metrics';
-import { ipMetrics, ipMetricsMapping } from './network_metrics';
-import { hostEntities, hostEntitiesMapping } from './host_entities';
-import {
- destinationCountryIsoCodeEntities,
- destinationCountryIsoCodeEntitiesMapping,
- destinationIpEntities,
- destinationIpEntitiesMapping,
- sourceCountryIsoCodeEntities,
- sourceCountryIsoCodeEntitiesMapping,
- sourceIpEntities,
- sourceIpEntitiesMapping,
-} from './network_entities';
-import { Mappings, Transforms } from './types';
-import { userEntities, userEntitiesMapping } from './user_entities';
-
-/**
- * These module names will map 1 to 1 to the REST interface.
- */
-export enum ModuleNames {
- hostSummaryMetrics = 'host_metrics',
- hostSummaryEntities = 'host_entities',
- networkSummaryEntities = 'network_entities',
- networkSummaryMetrics = 'network_metrics',
- userSummaryEntities = 'user_entities',
- userSummaryMetrics = 'user_metrics',
-}
-
-/**
- * Add any new folders as modules with their names below and grouped with
- * key values.
- */
-export const installableTransforms: Record = {
- [ModuleNames.hostSummaryMetrics]: [hostMetrics],
- [ModuleNames.hostSummaryEntities]: [hostEntities],
- [ModuleNames.networkSummaryEntities]: [
- destinationIpEntities,
- sourceIpEntities,
- destinationCountryIsoCodeEntities,
- sourceCountryIsoCodeEntities,
- ],
- [ModuleNames.networkSummaryMetrics]: [ipMetrics],
- [ModuleNames.userSummaryEntities]: [userEntities],
- [ModuleNames.userSummaryMetrics]: [userMetrics],
-};
-
-/**
- * For all the mapping types, add each with their names below and grouped with
- * key values.
- */
-export const installableMappings: Record = {
- [ModuleNames.hostSummaryMetrics]: [hostMetricsMapping],
- [ModuleNames.hostSummaryEntities]: [hostEntitiesMapping],
- [ModuleNames.networkSummaryEntities]: [
- sourceIpEntitiesMapping,
- destinationIpEntitiesMapping,
- destinationCountryIsoCodeEntitiesMapping,
- sourceCountryIsoCodeEntitiesMapping,
- ],
- [ModuleNames.networkSummaryMetrics]: [ipMetricsMapping],
- [ModuleNames.userSummaryEntities]: [userEntitiesMapping],
- [ModuleNames.userSummaryMetrics]: [userMetricsMapping],
-};
diff --git a/x-pack/plugins/metrics_entities/server/modules/network_entities/destination_country_iso_code_entities.json b/x-pack/plugins/metrics_entities/server/modules/network_entities/destination_country_iso_code_entities.json
deleted file mode 100644
index 1f39c6c9552bd..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/network_entities/destination_country_iso_code_entities.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
- "id": "dest_iso_ent",
- "description": "[destination.geo.country_iso_code entities] grouped by @timestamp and aggregated on source.bytes, destination.bytes, network.community_id, destination.ip, and source.ip",
- "pivot": {
- "group_by": {
- "@timestamp": {
- "date_histogram": {
- "field": "@timestamp",
- "calendar_interval": "1h"
- }
- },
- "destination.geo.country_iso_code": {
- "terms": {
- "field": "destination.geo.country_iso_code"
- }
- }
- },
- "aggregations": {
- "metrics.destination.geo.country_iso_code.value_count": {
- "value_count": {
- "field": "destination.geo.country_iso_code"
- }
- },
- "metrics.source.bytes.sum": {
- "sum": {
- "field": "source.bytes"
- }
- },
- "metrics.destination.bytes.sum": {
- "sum": {
- "field": "destination.bytes"
- }
- },
- "metrics.network.community_id.cardinality": {
- "cardinality": {
- "field": "network.community_id"
- }
- },
- "metrics.source.ip.cardinality": {
- "cardinality": {
- "field": "source.ip"
- }
- },
- "metrics.destination.ip.cardinality": {
- "cardinality": {
- "field": "destination.ip"
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/network_entities/destination_country_iso_code_entities_mapping.json b/x-pack/plugins/metrics_entities/server/modules/network_entities/destination_country_iso_code_entities_mapping.json
deleted file mode 100644
index e56ed7157afdc..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/network_entities/destination_country_iso_code_entities_mapping.json
+++ /dev/null
@@ -1,120 +0,0 @@
-{
- "mappings": {
- "_meta": {
- "index": "dest_iso_ent"
- },
- "dynamic": "strict",
- "properties": {
- "@timestamp": {
- "type": "date"
- },
- "metrics": {
- "properties": {
- "source": {
- "properties": {
- "ip": {
- "properties": {
- "value_count": {
- "type": "long"
- },
- "cardinality": {
- "type": "long"
- }
- }
- },
- "bytes": {
- "properties": {
- "sum": {
- "type": "long"
- }
- }
- },
- "geo": {
- "properties": {
- "country_iso_code": {
- "properties": {
- "value_count": {
- "type": "long"
- }
- }
- }
- }
- }
- }
- },
- "destination": {
- "properties": {
- "ip": {
- "properties": {
- "value_count": {
- "type": "long"
- },
- "cardinality": {
- "type": "long"
- }
- }
- },
- "bytes": {
- "properties": {
- "sum": {
- "type": "long"
- }
- }
- },
- "geo": {
- "properties": {
- "country_iso_code": {
- "properties": {
- "value_count": {
- "type": "long"
- }
- }
- }
- }
- }
- }
- },
- "network": {
- "properties": {
- "community_id": {
- "properties": {
- "cardinality": {
- "type": "long"
- }
- }
- }
- }
- }
- }
- },
- "source": {
- "properties": {
- "ip": {
- "type": "ip"
- },
- "geo": {
- "properties": {
- "country_iso_code": {
- "type": "keyword"
- }
- }
- }
- }
- },
- "destination": {
- "properties": {
- "ip": {
- "type": "ip"
- },
- "geo": {
- "properties": {
- "country_iso_code": {
- "type": "keyword"
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/network_entities/destination_ip_entities.json b/x-pack/plugins/metrics_entities/server/modules/network_entities/destination_ip_entities.json
deleted file mode 100644
index 7ecced9a11ebc..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/network_entities/destination_ip_entities.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "id": "dest_ip_ent",
- "description": "[destination.ip entities] grouped by @timestamp and aggregated on destination.ip, source.bytes, destination.bytes, network.community_id, and source.ip",
- "pivot": {
- "group_by": {
- "@timestamp": {
- "date_histogram": {
- "field": "@timestamp",
- "calendar_interval": "1h"
- }
- },
- "destination.ip": {
- "terms": {
- "field": "destination.ip"
- }
- }
- },
- "aggregations": {
- "metrics.destination.ip.value_count": {
- "value_count": {
- "field": "destination.ip"
- }
- },
- "metrics.source.bytes.sum": {
- "sum": {
- "field": "source.bytes"
- }
- },
- "metrics.destination.bytes.sum": {
- "sum": {
- "field": "destination.bytes"
- }
- },
- "metrics.network.community_id.cardinality": {
- "cardinality": {
- "field": "network.community_id"
- }
- },
- "metrics.source.ip.cardinality": {
- "cardinality": {
- "field": "source.ip"
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/network_entities/destination_ip_entities_mapping.json b/x-pack/plugins/metrics_entities/server/modules/network_entities/destination_ip_entities_mapping.json
deleted file mode 100644
index ef7e1050c9c5d..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/network_entities/destination_ip_entities_mapping.json
+++ /dev/null
@@ -1,84 +0,0 @@
-{
- "mappings": {
- "_meta": {
- "index": "dest_ip_ent"
- },
- "dynamic": "strict",
- "properties": {
- "@timestamp": {
- "type": "date"
- },
- "metrics": {
- "properties": {
- "source": {
- "properties": {
- "ip": {
- "properties": {
- "value_count": {
- "type": "long"
- },
- "cardinality": {
- "type": "long"
- }
- }
- },
- "bytes": {
- "properties": {
- "sum": {
- "type": "long"
- }
- }
- }
- }
- },
- "destination": {
- "properties": {
- "ip": {
- "properties": {
- "value_count": {
- "type": "long"
- },
- "cardinality": {
- "type": "long"
- }
- }
- },
- "bytes": {
- "properties": {
- "sum": {
- "type": "long"
- }
- }
- }
- }
- },
- "network": {
- "properties": {
- "community_id": {
- "properties": {
- "cardinality": {
- "type": "long"
- }
- }
- }
- }
- }
- }
- },
- "source": {
- "properties": {
- "ip": {
- "type": "ip"
- }
- }
- },
- "destination": {
- "properties": {
- "ip": {
- "type": "ip"
- }
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/network_entities/index.ts b/x-pack/plugins/metrics_entities/server/modules/network_entities/index.ts
deleted file mode 100644
index b54425763effb..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/network_entities/index.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import sourceIpEntities from './source_ip_entities.json';
-import destinationIpEntities from './destination_ip_entities.json';
-import sourceIpEntitiesMapping from './source_ip_entities_mapping.json';
-import destinationIpEntitiesMapping from './destination_ip_entities_mapping.json';
-import destinationCountryIsoCodeEntities from './destination_country_iso_code_entities.json';
-import destinationCountryIsoCodeEntitiesMapping from './destination_country_iso_code_entities_mapping.json';
-import sourceCountryIsoCodeEntities from './source_country_iso_code_entities.json';
-import sourceCountryIsoCodeEntitiesMapping from './source_country_iso_code_entities_mapping.json';
-
-export {
- sourceIpEntities,
- destinationIpEntities,
- sourceCountryIsoCodeEntities,
- sourceCountryIsoCodeEntitiesMapping,
- destinationCountryIsoCodeEntities,
- destinationCountryIsoCodeEntitiesMapping,
- sourceIpEntitiesMapping,
- destinationIpEntitiesMapping,
-};
diff --git a/x-pack/plugins/metrics_entities/server/modules/network_entities/source_country_iso_code_entities.json b/x-pack/plugins/metrics_entities/server/modules/network_entities/source_country_iso_code_entities.json
deleted file mode 100644
index 60021b975b21d..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/network_entities/source_country_iso_code_entities.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
- "id": "src_iso_ent",
- "description": "[source.geo.country_iso_code entities] grouped by @timestamp and aggregated on source.geo.country_iso_code, source.bytes, destination.bytes, network.community_id, source.ip, and destination.ip",
- "pivot": {
- "group_by": {
- "@timestamp": {
- "date_histogram": {
- "field": "@timestamp",
- "calendar_interval": "1h"
- }
- },
- "source.geo.country_iso_code": {
- "terms": {
- "field": "source.geo.country_iso_code"
- }
- }
- },
- "aggregations": {
- "metrics.source.geo.country_iso_code.value_count": {
- "value_count": {
- "field": "source.geo.country_iso_code"
- }
- },
- "metrics.source.bytes.sum": {
- "sum": {
- "field": "source.bytes"
- }
- },
- "metrics.destination.bytes.sum": {
- "sum": {
- "field": "destination.bytes"
- }
- },
- "metrics.network.community_id.cardinality": {
- "cardinality": {
- "field": "network.community_id"
- }
- },
- "metrics.source.ip.cardinality": {
- "cardinality": {
- "field": "source.ip"
- }
- },
- "metrics.destination.ip.cardinality": {
- "cardinality": {
- "field": "destination.ip"
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/network_entities/source_country_iso_code_entities_mapping.json b/x-pack/plugins/metrics_entities/server/modules/network_entities/source_country_iso_code_entities_mapping.json
deleted file mode 100644
index 0a44016be6a2c..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/network_entities/source_country_iso_code_entities_mapping.json
+++ /dev/null
@@ -1,120 +0,0 @@
-{
- "mappings": {
- "_meta": {
- "index": "src_iso_ent"
- },
- "dynamic": "strict",
- "properties": {
- "@timestamp": {
- "type": "date"
- },
- "metrics": {
- "properties": {
- "source": {
- "properties": {
- "ip": {
- "properties": {
- "value_count": {
- "type": "long"
- },
- "cardinality": {
- "type": "long"
- }
- }
- },
- "bytes": {
- "properties": {
- "sum": {
- "type": "long"
- }
- }
- },
- "geo": {
- "properties": {
- "country_iso_code": {
- "properties": {
- "value_count": {
- "type": "long"
- }
- }
- }
- }
- }
- }
- },
- "destination": {
- "properties": {
- "ip": {
- "properties": {
- "value_count": {
- "type": "long"
- },
- "cardinality": {
- "type": "long"
- }
- }
- },
- "bytes": {
- "properties": {
- "sum": {
- "type": "long"
- }
- }
- },
- "geo": {
- "properties": {
- "country_iso_code": {
- "properties": {
- "value_count": {
- "type": "long"
- }
- }
- }
- }
- }
- }
- },
- "network": {
- "properties": {
- "community_id": {
- "properties": {
- "cardinality": {
- "type": "long"
- }
- }
- }
- }
- }
- }
- },
- "source": {
- "properties": {
- "ip": {
- "type": "ip"
- },
- "geo": {
- "properties": {
- "country_iso_code": {
- "type": "keyword"
- }
- }
- }
- }
- },
- "destination": {
- "properties": {
- "ip": {
- "type": "ip"
- },
- "geo": {
- "properties": {
- "country_iso_code": {
- "type": "keyword"
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/network_entities/source_ip_entities.json b/x-pack/plugins/metrics_entities/server/modules/network_entities/source_ip_entities.json
deleted file mode 100644
index 3de6669c7bedb..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/network_entities/source_ip_entities.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "id": "src_ip_ent",
- "description": "[source.ip entities] grouped by @timestamp and aggregated on destination.ip, source.bytes, destination.bytes, network.community_id, and destination.ip",
- "pivot": {
- "group_by": {
- "@timestamp": {
- "date_histogram": {
- "field": "@timestamp",
- "calendar_interval": "1h"
- }
- },
- "source.ip": {
- "terms": {
- "field": "source.ip"
- }
- }
- },
- "aggregations": {
- "metrics.source.ip.value_count": {
- "value_count": {
- "field": "source.ip"
- }
- },
- "metrics.source.bytes.sum": {
- "sum": {
- "field": "source.bytes"
- }
- },
- "metrics.destination.bytes.sum": {
- "sum": {
- "field": "destination.bytes"
- }
- },
- "metrics.network.community_id.cardinality": {
- "cardinality": {
- "field": "network.community_id"
- }
- },
- "metrics.destination.ip.cardinality": {
- "cardinality": {
- "field": "destination.ip"
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/network_entities/source_ip_entities_mapping.json b/x-pack/plugins/metrics_entities/server/modules/network_entities/source_ip_entities_mapping.json
deleted file mode 100644
index 64d9e48afcee9..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/network_entities/source_ip_entities_mapping.json
+++ /dev/null
@@ -1,84 +0,0 @@
-{
- "mappings": {
- "_meta": {
- "index": "src_ip_ent"
- },
- "dynamic": "strict",
- "properties": {
- "@timestamp": {
- "type": "date"
- },
- "metrics": {
- "properties": {
- "source": {
- "properties": {
- "ip": {
- "properties": {
- "value_count": {
- "type": "long"
- },
- "cardinality": {
- "type": "long"
- }
- }
- },
- "bytes": {
- "properties": {
- "sum": {
- "type": "long"
- }
- }
- }
- }
- },
- "destination": {
- "properties": {
- "ip": {
- "properties": {
- "value_count": {
- "type": "long"
- },
- "cardinality": {
- "type": "long"
- }
- }
- },
- "bytes": {
- "properties": {
- "sum": {
- "type": "long"
- }
- }
- }
- }
- },
- "network": {
- "properties": {
- "community_id": {
- "properties": {
- "cardinality": {
- "type": "long"
- }
- }
- }
- }
- }
- }
- },
- "source": {
- "properties": {
- "ip": {
- "type": "ip"
- }
- }
- },
- "destination": {
- "properties": {
- "ip": {
- "type": "ip"
- }
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/network_metrics/index.ts b/x-pack/plugins/metrics_entities/server/modules/network_metrics/index.ts
deleted file mode 100644
index 216b85234dda4..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/network_metrics/index.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import ipMetrics from './ip_metrics.json';
-import ipMetricsMapping from './ip_metrics_mapping.json';
-
-export { ipMetrics, ipMetricsMapping };
diff --git a/x-pack/plugins/metrics_entities/server/modules/network_metrics/ip_metrics.json b/x-pack/plugins/metrics_entities/server/modules/network_metrics/ip_metrics.json
deleted file mode 100644
index ed953be84f3da..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/network_metrics/ip_metrics.json
+++ /dev/null
@@ -1,116 +0,0 @@
-{
- "id": "ip_met",
- "description": "[source.ip metrics] grouped by @timestamp, source.ip, destination.ip and aggregated on tls.version, suricata.eve.tls.version, zeek.ssl.version, dns.question.name, and zeek.dns.query",
- "pivot": {
- "group_by": {
- "@timestamp": {
- "date_histogram": {
- "field": "@timestamp",
- "calendar_interval": "1h"
- }
- }
- },
- "aggregations": {
- "metrics.source.ip.cardinality": {
- "cardinality": {
- "field": "source.ip"
- }
- },
- "metrics.destination.ip.cardinality": {
- "cardinality": {
- "field": "destination.ip"
- }
- },
- "metrics.network": {
- "filter": {
- "bool": {
- "should": [
- {
- "exists": {
- "field": "source.ip"
- }
- },
- {
- "exists": {
- "field": "destination.ip"
- }
- }
- ],
- "minimum_should_match": 1
- }
- },
- "aggs": {
- "events.value_count": {
- "value_count": {
- "field": "@timestamp"
- }
- },
- "tls": {
- "filter": {
- "bool": {
- "should": [
- {
- "exists": {
- "field": "tls.version"
- }
- },
- {
- "exists": {
- "field": "suricata.eve.tls.version"
- }
- },
- {
- "exists": {
- "field": "zeek.ssl.version"
- }
- }
- ],
- "minimum_should_match": 1
- }
- },
- "aggs": {
- "version.value_count": {
- "value_count": {
- "field": "@timestamp"
- }
- }
- }
- }
- }
- },
- "metrics.dns": {
- "filter": {
- "bool": {
- "should": [
- {
- "exists": {
- "field": "dns.question.name"
- }
- },
- {
- "term": {
- "suricata.eve.dns.type": {
- "value": "query"
- }
- }
- },
- {
- "exists": {
- "field": "zeek.dns.query"
- }
- }
- ],
- "minimum_should_match": 1
- }
- },
- "aggs": {
- "queries.value_count": {
- "value_count": {
- "field": "@timestamp"
- }
- }
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/network_metrics/ip_metrics_mapping.json b/x-pack/plugins/metrics_entities/server/modules/network_metrics/ip_metrics_mapping.json
deleted file mode 100644
index a855b6091f29c..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/network_metrics/ip_metrics_mapping.json
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- "mappings": {
- "_meta": {
- "index": "ip_met"
- },
- "dynamic": "strict",
- "properties": {
- "@timestamp": {
- "type": "date"
- },
- "metrics": {
- "properties": {
- "source": {
- "properties": {
- "ip": {
- "properties": {
- "value_count": {
- "type": "long"
- },
- "cardinality": {
- "type": "long"
- }
- }
- },
- "bytes": {
- "properties": {
- "sum": {
- "type": "long"
- }
- }
- }
- }
- },
- "destination": {
- "properties": {
- "ip": {
- "properties": {
- "value_count": {
- "type": "long"
- },
- "cardinality": {
- "type": "long"
- }
- }
- },
- "bytes": {
- "properties": {
- "sum": {
- "type": "long"
- }
- }
- }
- }
- },
- "network": {
- "properties": {
- "events": {
- "properties": {
- "value_count": {
- "type": "long"
- }
- }
- },
- "tls": {
- "properties": {
- "version": {
- "properties": {
- "value_count": {
- "type": "long"
- }
- }
- }
- }
- }
- }
- },
- "dns": {
- "properties": {
- "queries": {
- "properties": {
- "value_count": {
- "type": "long"
- }
- }
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/types.ts b/x-pack/plugins/metrics_entities/server/modules/types.ts
deleted file mode 100644
index 22b11ed89f5c4..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/types.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-/**
- * Loose type for the mappings
- */
-export interface Mappings {
- [key: string]: unknown;
- mappings: {
- [key: string]: unknown;
- _meta: {
- index: string;
- };
- };
-}
-
-/**
- * Loose type for the transforms. id is marked optional so we can delete it before
- * pushing it through elastic client.
- * TODO: Can we use stricter pre-defined typings for the transforms here or is this ours because we define it slightly different?
- */
-export interface Transforms {
- [key: string]: unknown;
- id: string;
- dest?: Partial<{
- index: string;
- pipeline: string;
- }>;
- source?: Partial<{}>;
- settings?: Partial<{
- max_page_search_size: number;
- docs_per_second: number | null;
- }>;
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/user_entities/index.ts b/x-pack/plugins/metrics_entities/server/modules/user_entities/index.ts
deleted file mode 100644
index 9cc17c8f180f0..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/user_entities/index.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import userEntities from './user_entities.json';
-import userEntitiesMapping from './user_entities_mapping.json';
-export { userEntities, userEntitiesMapping };
diff --git a/x-pack/plugins/metrics_entities/server/modules/user_entities/user_entities.json b/x-pack/plugins/metrics_entities/server/modules/user_entities/user_entities.json
deleted file mode 100644
index aa41edcf40d41..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/user_entities/user_entities.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
- "id": "user_ent",
- "description": "[user.name entities] grouped by @timestamp and aggregated on user.name, and event.categories of success, failure, and unknown",
- "pivot": {
- "group_by": {
- "@timestamp": {
- "date_histogram": {
- "field": "@timestamp",
- "calendar_interval": "1h"
- }
- },
- "user.name": {
- "terms": {
- "field": "user.name"
- }
- }
- },
- "aggregations": {
- "metrics.event.authentication": {
- "filter": {
- "term": {
- "event.category": "authentication"
- }
- },
- "aggs": {
- "success.value_count": {
- "filter": {
- "term": {
- "event.outcome": "success"
- }
- }
- },
- "failure.value_count": {
- "filter": {
- "term": {
- "event.outcome": "failure"
- }
- }
- },
- "unknown.value_count": {
- "filter": {
- "term": {
- "event.outcome": "unknown"
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/user_entities/user_entities_mapping.json b/x-pack/plugins/metrics_entities/server/modules/user_entities/user_entities_mapping.json
deleted file mode 100644
index 2532afa3040c6..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/user_entities/user_entities_mapping.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{
- "mappings": {
- "_meta": {
- "index": "user_ent"
- },
- "dynamic": "strict",
- "properties": {
- "@timestamp": {
- "type": "date"
- },
- "metrics": {
- "properties": {
- "event": {
- "properties": {
- "authentication": {
- "properties": {
- "failure": {
- "properties": {
- "value_count": {
- "type": "long"
- }
- }
- },
- "success": {
- "properties": {
- "value_count": {
- "type": "long"
- }
- }
- },
- "unknown": {
- "properties": {
- "value_count": {
- "type": "long"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "user": {
- "properties": {
- "name": {
- "type": "keyword"
- }
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/user_metrics/index.ts b/x-pack/plugins/metrics_entities/server/modules/user_metrics/index.ts
deleted file mode 100644
index b7c6e65155ed2..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/user_metrics/index.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import userMetrics from './user_metrics.json';
-import userMetricsMapping from './user_metrics_mapping.json';
-
-export { userMetrics, userMetricsMapping };
diff --git a/x-pack/plugins/metrics_entities/server/modules/user_metrics/user_metrics.json b/x-pack/plugins/metrics_entities/server/modules/user_metrics/user_metrics.json
deleted file mode 100644
index 86154bd8c68ec..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/user_metrics/user_metrics.json
+++ /dev/null
@@ -1,56 +0,0 @@
-{
- "id": "user_met",
- "description": "[event.category authentication metrics] grouped by @timestamp and aggregated on success, failure, and unknown",
- "source": {
- "query": {
- "bool": {
- "filter": [
- {
- "bool": {
- "filter": [
- {
- "term": {
- "event.category": "authentication"
- }
- }
- ]
- }
- }
- ]
- }
- }
- },
- "pivot": {
- "group_by": {
- "@timestamp": {
- "date_histogram": {
- "field": "@timestamp",
- "calendar_interval": "1h"
- }
- }
- },
- "aggregations": {
- "metrics.event.authentication.success.value_count": {
- "filter": {
- "term": {
- "event.outcome": "success"
- }
- }
- },
- "metrics.event.authentication.failure.value_count": {
- "filter": {
- "term": {
- "event.outcome": "failure"
- }
- }
- },
- "metrics.event.authentication.unknown.value_count": {
- "filter": {
- "term": {
- "event.outcome": "unknown"
- }
- }
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/modules/user_metrics/user_metrics_mapping.json b/x-pack/plugins/metrics_entities/server/modules/user_metrics/user_metrics_mapping.json
deleted file mode 100644
index c63dcd2b4a429..0000000000000
--- a/x-pack/plugins/metrics_entities/server/modules/user_metrics/user_metrics_mapping.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "mappings": {
- "_meta": {
- "index": "user_met"
- },
- "dynamic": "strict",
- "properties": {
- "metrics": {
- "properties": {
- "event": {
- "properties": {
- "authentication": {
- "properties": {
- "failure": {
- "properties": {
- "value_count": {
- "type": "long"
- }
- }
- },
- "success": {
- "properties": {
- "value_count": {
- "type": "long"
- }
- }
- },
- "unknown": {
- "properties": {
- "value_count": {
- "type": "long"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "@timestamp": {
- "type": "date"
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/plugin.ts b/x-pack/plugins/metrics_entities/server/plugin.ts
deleted file mode 100644
index c2eb16a1f616e..0000000000000
--- a/x-pack/plugins/metrics_entities/server/plugin.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import {
- CoreSetup,
- CoreStart,
- Logger,
- Plugin,
- PluginInitializerContext,
-} from '../../../../src/core/server';
-
-import {
- ContextProvider,
- ContextProviderReturn,
- MetricsEntitiesPluginSetup,
- MetricsEntitiesPluginStart,
- MetricsEntitiesRequestHandlerContext,
-} from './types';
-import { getTransforms, postTransforms } from './routes';
-import { MetricsEntitiesClient } from './services/metrics_entities_client';
-import { deleteTransforms } from './routes/delete_transforms';
-
-export class MetricsEntitiesPlugin
- implements Plugin
-{
- private readonly logger: Logger;
- private kibanaVersion: string;
-
- constructor(initializerContext: PluginInitializerContext) {
- this.logger = initializerContext.logger.get();
- this.kibanaVersion = initializerContext.env.packageInfo.version;
- }
-
- public setup(core: CoreSetup): MetricsEntitiesPluginSetup {
- const router = core.http.createRouter();
-
- core.http.registerRouteHandlerContext(
- 'metricsEntities',
- this.createRouteHandlerContext()
- );
-
- // Register server side APIs
- // TODO: Add all of these into a separate file and call that file called init_routes.ts
- getTransforms(router);
- postTransforms(router);
- deleteTransforms(router);
-
- return {
- getMetricsEntitiesClient: (esClient): MetricsEntitiesClient =>
- new MetricsEntitiesClient({
- esClient,
- kibanaVersion: this.kibanaVersion,
- logger: this.logger,
- }),
- };
- }
-
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- public start(core: CoreStart): void {
- this.logger.debug('Starting plugin');
- }
-
- public stop(): void {
- this.logger.debug('Stopping plugin');
- }
-
- private createRouteHandlerContext = (): ContextProvider => {
- return async (context): ContextProviderReturn => {
- const {
- core: {
- elasticsearch: {
- client: { asCurrentUser: esClient },
- },
- },
- } = context;
- return {
- getMetricsEntitiesClient: (): MetricsEntitiesClient =>
- new MetricsEntitiesClient({
- esClient,
- kibanaVersion: this.kibanaVersion,
- logger: this.logger,
- }),
- };
- };
- };
-}
diff --git a/x-pack/plugins/metrics_entities/server/routes/delete_transforms.ts b/x-pack/plugins/metrics_entities/server/routes/delete_transforms.ts
deleted file mode 100644
index 531e90963add4..0000000000000
--- a/x-pack/plugins/metrics_entities/server/routes/delete_transforms.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { schema } from '@kbn/config-schema';
-
-import { IRouter } from '../../../../../src/core/server';
-import { METRICS_ENTITIES_TRANSFORMS } from '../../common/constants';
-import { ModuleNames } from '../modules';
-
-import { getMetricsEntitiesClient } from './utils/get_metrics_entities_client';
-
-/**
- * Deletes transforms.
- * NOTE: We use a POST rather than a DELETE on purpose here to ensure that there
- * are not problems with the body being sent.
- * @param router The router to delete the collection of transforms
- */
-export const deleteTransforms = (router: IRouter): void => {
- router.post(
- {
- path: `${METRICS_ENTITIES_TRANSFORMS}/_delete`,
- validate: {
- // TODO: Add the validation instead of allowing handler to have access to raw non-validated in runtime
- body: schema.object({}, { unknowns: 'allow' }),
- query: schema.object({}, { unknowns: 'allow' }),
- },
- },
- async (context, request, response) => {
- // TODO: Type this through validation above and remove the weird casting of: "as { modules: ModuleNames };"
- // TODO: Validate for runtime that the module exists or not and throw before pushing the module name lower
- // TODO: Change modules to be part of the body and become an array of values
- // TODO: Wrap this in a try catch block and report errors
- const {
- modules,
- prefix = '',
- suffix = '',
- } = request.body as {
- modules: ModuleNames[];
- prefix: string;
- suffix: string;
- };
- const metrics = getMetricsEntitiesClient(context);
- await metrics.deleteTransforms({ modules, prefix, suffix });
-
- return response.custom({
- statusCode: 204,
- });
- }
- );
-};
diff --git a/x-pack/plugins/metrics_entities/server/routes/get_transforms.ts b/x-pack/plugins/metrics_entities/server/routes/get_transforms.ts
deleted file mode 100644
index cda61512ce293..0000000000000
--- a/x-pack/plugins/metrics_entities/server/routes/get_transforms.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { IRouter } from '../../../../../src/core/server';
-import { METRICS_ENTITIES_TRANSFORMS } from '../../common/constants';
-
-import { getMetricsEntitiesClient } from './utils/get_metrics_entities_client';
-
-/**
- * Returns all transforms from all modules
- * TODO: Add support for specific modules and prefix
- * @param router The router to get the collection of transforms
- */
-export const getTransforms = (router: IRouter): void => {
- router.get(
- {
- path: METRICS_ENTITIES_TRANSFORMS,
- // TODO: Add the validation instead of false
- // TODO: Add the prefix and module support
- validate: false,
- },
- async (context, _, response) => {
- const metrics = getMetricsEntitiesClient(context);
- const summaries = await metrics.getTransforms();
- return response.ok({
- body: {
- summaries,
- },
- });
- }
- );
-};
diff --git a/x-pack/plugins/metrics_entities/server/routes/index.ts b/x-pack/plugins/metrics_entities/server/routes/index.ts
deleted file mode 100644
index 9470772f46d70..0000000000000
--- a/x-pack/plugins/metrics_entities/server/routes/index.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-export * from './delete_transforms';
-export * from './get_transforms';
-export * from './post_transforms';
diff --git a/x-pack/plugins/metrics_entities/server/routes/post_transforms.ts b/x-pack/plugins/metrics_entities/server/routes/post_transforms.ts
deleted file mode 100644
index f5a46ec04611d..0000000000000
--- a/x-pack/plugins/metrics_entities/server/routes/post_transforms.ts
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { schema } from '@kbn/config-schema';
-
-import { IRouter } from '../../../../../src/core/server';
-import { METRICS_ENTITIES_TRANSFORMS } from '../../common/constants';
-import { ModuleNames } from '../modules';
-
-import { getMetricsEntitiesClient } from './utils/get_metrics_entities_client';
-
-/**
- * Creates transforms.
- * @param router The router to get the collection of transforms
- */
-export const postTransforms = (router: IRouter): void => {
- router.post(
- {
- path: METRICS_ENTITIES_TRANSFORMS,
- validate: {
- // TODO: Add the validation instead of allowing handler to have access to raw non-validated in runtime
- body: schema.object({}, { unknowns: 'allow' }),
- query: schema.object({}, { unknowns: 'allow' }),
- },
- },
- async (context, request, response) => {
- // TODO: Type this through validation above and remove the weird casting of: "as { modules: ModuleNames };"
- // TODO: Validate for runtime that the module exists or not and throw before pushing the module name lower
- // TODO: Change modules to be part of the body and become an array of values
- // TODO: Wrap this in a try catch block and report errors
- const {
- modules,
- auto_start: autoStart = false,
- settings: {
- max_page_search_size: maxPageSearchSize = 500,
- docs_per_second: docsPerSecond = undefined,
- } = {
- docsPerSecond: undefined,
- maxPageSearchSize: 500,
- },
- frequency = '1m',
- indices,
- query = { match_all: {} },
- prefix = '',
- suffix = '',
- sync = {
- time: {
- delay: '60s',
- field: '@timestamp',
- },
- },
- } = request.body as {
- modules: ModuleNames[];
- auto_start: boolean;
- indices: string[];
- // We can blow up at 65 character+ for transform id. We need to validate the prefix + transform jobs and return an error
- prefix: string;
- query: object;
- suffix: string;
- frequency: string;
- settings: {
- max_page_search_size: number;
- docs_per_second: number;
- };
- sync: {
- time: {
- delay: string;
- field: string;
- };
- };
- };
- const metrics = getMetricsEntitiesClient(context);
- await metrics.postTransforms({
- autoStart,
- docsPerSecond,
- frequency,
- indices,
- maxPageSearchSize,
- modules,
- prefix,
- query,
- suffix,
- sync,
- });
-
- return response.custom({
- body: { acknowledged: true },
- statusCode: 201,
- });
- }
- );
-};
diff --git a/x-pack/plugins/metrics_entities/server/routes/utils/get_metrics_entities_client.ts b/x-pack/plugins/metrics_entities/server/routes/utils/get_metrics_entities_client.ts
deleted file mode 100644
index fdbbd98128741..0000000000000
--- a/x-pack/plugins/metrics_entities/server/routes/utils/get_metrics_entities_client.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ErrorWithStatusCode } from '../../error_with_status_code';
-import { MetricsEntitiesClient } from '../../services/metrics_entities_client';
-import type { MetricsEntitiesRequestHandlerContext } from '../../types';
-
-export const getMetricsEntitiesClient = (
- context: MetricsEntitiesRequestHandlerContext
-): MetricsEntitiesClient => {
- const metricsEntities = context.metricsEntities?.getMetricsEntitiesClient();
- if (metricsEntities == null) {
- throw new ErrorWithStatusCode('Metrics Entities is not found as a plugin', 404);
- } else {
- return metricsEntities;
- }
-};
diff --git a/x-pack/plugins/metrics_entities/server/routes/utils/index.ts b/x-pack/plugins/metrics_entities/server/routes/utils/index.ts
deleted file mode 100644
index eee678d64b30d..0000000000000
--- a/x-pack/plugins/metrics_entities/server/routes/utils/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-export * from './get_metrics_entities_client';
diff --git a/x-pack/plugins/metrics_entities/server/scripts/check_env_variables.sh b/x-pack/plugins/metrics_entities/server/scripts/check_env_variables.sh
deleted file mode 100755
index df2354ed8398a..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/check_env_variables.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
-# or more contributor license agreements. Licensed under the Elastic License
-# 2.0; you may not use this file except in compliance with the Elastic License
-# 2.0.
-#
-
-# Add this to the start of any scripts to detect if env variables are set
-
-set -e
-
-if [ -z "${ELASTICSEARCH_USERNAME}" ]; then
- echo "Set ELASTICSEARCH_USERNAME in your environment"
- exit 1
-fi
-
-if [ -z "${ELASTICSEARCH_PASSWORD}" ]; then
- echo "Set ELASTICSEARCH_PASSWORD in your environment"
- exit 1
-fi
-
-if [ -z "${ELASTICSEARCH_URL}" ]; then
- echo "Set ELASTICSEARCH_URL in your environment"
- exit 1
-fi
-
-if [ -z "${KIBANA_URL}" ]; then
- echo "Set KIBANA_URL in your environment"
- exit 1
-fi
diff --git a/x-pack/plugins/metrics_entities/server/scripts/delete_examples/all.json b/x-pack/plugins/metrics_entities/server/scripts/delete_examples/all.json
deleted file mode 100644
index b07028d0cab89..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/delete_examples/all.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "prefix": "all",
- "modules": [
- "host_metrics",
- "host_entities",
- "network_metrics",
- "network_entities",
- "user_entities",
- "user_metrics"
- ]
-}
diff --git a/x-pack/plugins/metrics_entities/server/scripts/delete_examples/all_prefix_auditbeat.json b/x-pack/plugins/metrics_entities/server/scripts/delete_examples/all_prefix_auditbeat.json
deleted file mode 100644
index 5b20203075924..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/delete_examples/all_prefix_auditbeat.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "prefix": "auditbeat",
- "modules": [
- "host_metrics",
- "host_entities",
- "network_metrics",
- "network_entities",
- "user_entities",
- "user_metrics"
- ]
-}
diff --git a/x-pack/plugins/metrics_entities/server/scripts/delete_examples/network_entities_auditbeat.json b/x-pack/plugins/metrics_entities/server/scripts/delete_examples/network_entities_auditbeat.json
deleted file mode 100644
index b1e21ebbc9bd6..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/delete_examples/network_entities_auditbeat.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "modules": ["network_entities"]
-}
diff --git a/x-pack/plugins/metrics_entities/server/scripts/delete_examples/one_module.json b/x-pack/plugins/metrics_entities/server/scripts/delete_examples/one_module.json
deleted file mode 100644
index 2e9a62b9fbe82..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/delete_examples/one_module.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "modules": ["user_entities"]
-}
diff --git a/x-pack/plugins/metrics_entities/server/scripts/delete_examples/two_modules.json b/x-pack/plugins/metrics_entities/server/scripts/delete_examples/two_modules.json
deleted file mode 100644
index e3292834f3d08..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/delete_examples/two_modules.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "modules": ["host_metrics", "host_entities"]
-}
diff --git a/x-pack/plugins/metrics_entities/server/scripts/delete_transforms.sh b/x-pack/plugins/metrics_entities/server/scripts/delete_transforms.sh
deleted file mode 100755
index d4c03411cbcca..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/delete_transforms.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
-# or more contributor license agreements. Licensed under the Elastic License
-# 2.0; you may not use this file except in compliance with the Elastic License
-# 2.0.
-#
-
-set -e
-./check_env_variables.sh
-
-# Uses a default if no argument is specified
-FILE=${1:-./post_examples/one_module.json}
-
-# Example: ./delete_transforms.sh ./delete_examples/one_module.json
-curl -s -k \
- -H 'Content-Type: application/json' \
- -H 'kbn-xsrf: 123' \
- -u ${ELASTICSEARCH_USERNAME}:${ELASTICSEARCH_PASSWORD} \
- -X POST ${KIBANA_URL}${SPACE_URL}/api/metrics_entities/transforms/_delete \
- -d @${FILE} \
- | jq .
diff --git a/x-pack/plugins/metrics_entities/server/scripts/get_transforms.sh b/x-pack/plugins/metrics_entities/server/scripts/get_transforms.sh
deleted file mode 100755
index 34f7e4b83cc39..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/get_transforms.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
-# or more contributor license agreements. Licensed under the Elastic License
-# 2.0; you may not use this file except in compliance with the Elastic License
-# 2.0.
-#
-
-set -e
-./check_env_variables.sh
-
-# Example: ./get_transforms.sh
-curl -s -k \
- -u ${ELASTICSEARCH_USERNAME}:${ELASTICSEARCH_PASSWORD} \
- -X GET ${KIBANA_URL}${SPACE_URL}/api/metrics_entities/transforms | jq .
diff --git a/x-pack/plugins/metrics_entities/server/scripts/hard_reset.sh b/x-pack/plugins/metrics_entities/server/scripts/hard_reset.sh
deleted file mode 100755
index 69acf10764936..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/hard_reset.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
-# or more contributor license agreements. Licensed under the Elastic License
-# 2.0; you may not use this file except in compliance with the Elastic License
-# 2.0.
-#
-
-# TODO Make this work
-
-set -e
-./check_env_variables.sh
-
-# remove all templates
-# add all templates again and start them
-
diff --git a/x-pack/plugins/metrics_entities/server/scripts/post_examples/all.json b/x-pack/plugins/metrics_entities/server/scripts/post_examples/all.json
deleted file mode 100644
index dac53a63dad55..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/post_examples/all.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "prefix": "all",
- "modules": [
- "host_metrics",
- "host_entities",
- "network_metrics",
- "network_entities",
- "user_entities",
- "user_metrics"
- ],
- "indices": [
- "auditbeat-*",
- "endgame-*",
- "filebeat-*",
- "logs-*",
- "packetbeat-*",
- "winlogbeat-*",
- "-*elastic-cloud-logs-*"
- ],
- "auto_start": true,
- "settings": {
- "max_page_search_size": 5000
- },
- "query": {
- "range": {
- "@timestamp": {
- "gte": "now-1d/d",
- "format": "strict_date_optional_time"
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/scripts/post_examples/all_auditbeat.json b/x-pack/plugins/metrics_entities/server/scripts/post_examples/all_auditbeat.json
deleted file mode 100644
index 5a2f6b5024689..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/post_examples/all_auditbeat.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "modules": [
- "host_metrics",
- "host_entities",
- "network_metrics",
- "network_entities",
- "user_entities",
- "user_metrics"
- ],
- "indices": ["auditbeat-*"],
- "auto_start": true,
- "settings": {
- "max_page_search_size": 5000
- },
- "query": {
- "range": {
- "@timestamp": {
- "gte": "now-1d/d",
- "format": "strict_date_optional_time"
- }
- }
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/scripts/post_examples/network_entities_auditbeat.json b/x-pack/plugins/metrics_entities/server/scripts/post_examples/network_entities_auditbeat.json
deleted file mode 100644
index 379a5733a91f9..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/post_examples/network_entities_auditbeat.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "modules": ["network_entities"],
- "indices": ["auditbeat-*"]
-}
diff --git a/x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_allindices_autostart.json b/x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_allindices_autostart.json
deleted file mode 100644
index 9872706ff1ac2..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_allindices_autostart.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "modules": ["network_metrics"],
- "indices": [
- "auditbeat-*",
- "endgame-*",
- "filebeat-*",
- "logs-*",
- "packetbeat-*",
- "winlogbeat-*",
- "-*elastic-cloud-logs-*"
- ],
- "auto_start": true,
- "query": {
- "range": {
- "@timestamp": {
- "gte": "now-1d/d",
- "format": "strict_date_optional_time"
- }
- }
- },
- "settings": {
- "max_page_search_size": 5000
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_auditbeat.json b/x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_auditbeat.json
deleted file mode 100644
index 4ce4db5da9f23..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_auditbeat.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "modules": ["network_metrics"],
- "indices": ["auditbeat-*"],
- "auto_start": true,
- "query": {
- "range": {
- "@timestamp": {
- "gte": "now-1d/d",
- "format": "strict_date_optional_time"
- }
- }
- },
- "settings": {
- "max_page_search_size": 5000
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_auto_start.json b/x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_auto_start.json
deleted file mode 100644
index d5a87c80a44a0..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_auto_start.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "modules": ["host_metrics"],
- "indices": ["auditbeat-*"],
- "auto_start": true,
- "settings": {
- "max_page_search_size": 5000
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_prefix_auditbeat.json b/x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_prefix_auditbeat.json
deleted file mode 100644
index f20875f28ffa3..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/post_examples/one_module_prefix_auditbeat.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "modules": ["host_metrics"],
- "indices": ["auditbeat-*"],
- "prefix": ["default_"]
-}
diff --git a/x-pack/plugins/metrics_entities/server/scripts/post_examples/two_modules_all.json b/x-pack/plugins/metrics_entities/server/scripts/post_examples/two_modules_all.json
deleted file mode 100644
index 8ec9401b94433..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/post_examples/two_modules_all.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "modules": ["network_metrics", "network_entities"],
- "indices": [
- "auditbeat-*",
- "endgame-*",
- "filebeat-*",
- "logs-*",
- "packetbeat-*",
- "winlogbeat-*",
- "-*elastic-cloud-logs-*"
- ],
- "auto_start": true,
- "query": {
- "range": {
- "@timestamp": {
- "gte": "now-1d/d",
- "format": "strict_date_optional_time"
- }
- }
- },
- "settings": {
- "max_page_search_size": 5000
- }
-}
diff --git a/x-pack/plugins/metrics_entities/server/scripts/post_examples/two_modules_auditbeat.json b/x-pack/plugins/metrics_entities/server/scripts/post_examples/two_modules_auditbeat.json
deleted file mode 100644
index 5229cd88fc433..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/post_examples/two_modules_auditbeat.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "modules": ["host_metrics", "host_entities"],
- "indices": ["auditbeat-*"]
-}
diff --git a/x-pack/plugins/metrics_entities/server/scripts/post_transforms.sh b/x-pack/plugins/metrics_entities/server/scripts/post_transforms.sh
deleted file mode 100755
index 9dd4169cc01d6..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/post_transforms.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
-# or more contributor license agreements. Licensed under the Elastic License
-# 2.0; you may not use this file except in compliance with the Elastic License
-# 2.0.
-#
-
-set -e
-./check_env_variables.sh
-
-# Uses a default if no argument is specified
-FILE=${1:-./post_examples/one_module_auditbeat.json}
-
-# Example: ./post_transforms.sh ./post_examples/one_module_auditbeat.json
-# Example: ./post_transforms.sh ./post_examples/one_module_namespace_auditbeat.json
-curl -s -k \
- -H 'Content-Type: application/json' \
- -H 'kbn-xsrf: 123' \
- -u ${ELASTICSEARCH_USERNAME}:${ELASTICSEARCH_PASSWORD} \
- -X POST ${KIBANA_URL}${SPACE_URL}/api/metrics_entities/transforms \
- -d @${FILE} \
- | jq .
diff --git a/x-pack/plugins/metrics_entities/server/scripts/update_transforms.sh b/x-pack/plugins/metrics_entities/server/scripts/update_transforms.sh
deleted file mode 100755
index bccf49e2d1b0d..0000000000000
--- a/x-pack/plugins/metrics_entities/server/scripts/update_transforms.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
-# or more contributor license agreements. Licensed under the Elastic License
-# 2.0; you may not use this file except in compliance with the Elastic License
-# 2.0.
-#
-
-set -e
-./check_env_variables.sh
-
-# TODO Make this work
diff --git a/x-pack/plugins/metrics_entities/server/services/delete_transforms.ts b/x-pack/plugins/metrics_entities/server/services/delete_transforms.ts
deleted file mode 100644
index ef172bcbf7c02..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/delete_transforms.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ElasticsearchClient } from 'kibana/server';
-
-import { ModuleNames, installableMappings, installableTransforms } from '../modules';
-import type { Logger } from '../../../../../src/core/server';
-
-import { uninstallMappings } from './uninstall_mappings';
-import { uninstallTransforms } from './uninstall_transforms';
-
-interface DeleteTransformsOptions {
- esClient: ElasticsearchClient;
- logger: Logger;
- modules: ModuleNames[];
- prefix: string;
- suffix: string;
-}
-
-export const deleteTransforms = async ({
- esClient,
- logger,
- modules,
- prefix,
- suffix,
-}: DeleteTransformsOptions): Promise => {
- for (const moduleName of modules) {
- const mappings = installableMappings[moduleName];
- const transforms = installableTransforms[moduleName];
-
- await uninstallTransforms({ esClient, logger, prefix, suffix, transforms });
- await uninstallMappings({ esClient, logger, mappings, prefix, suffix });
- }
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/get_transforms.ts b/x-pack/plugins/metrics_entities/server/services/get_transforms.ts
deleted file mode 100644
index 07c3d95b0943a..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/get_transforms.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ElasticsearchClient } from 'kibana/server';
-
-import type { Logger } from '../../../../../src/core/server';
-
-interface GetTransformsOptions {
- esClient: ElasticsearchClient;
- logger: Logger;
-}
-
-// TODO: Type the Promise to a stronger type
-export const getTransforms = async ({ esClient }: GetTransformsOptions): Promise => {
- const body = await esClient.transform.getTransform({
- size: 1000,
- transform_id: '*',
- });
- return body;
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/index.ts b/x-pack/plugins/metrics_entities/server/services/index.ts
deleted file mode 100644
index 71611d2a5eae0..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/index.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-export * from './delete_transforms';
-export * from './get_transforms';
-export * from './install_mappings';
-export * from './install_transforms';
-export * from './metrics_entities_client';
-export * from './post_transforms';
-export * from './uninstall_mappings';
-export * from './uninstall_transforms';
diff --git a/x-pack/plugins/metrics_entities/server/services/install_mappings.ts b/x-pack/plugins/metrics_entities/server/services/install_mappings.ts
deleted file mode 100644
index da42f9916ff9b..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/install_mappings.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ElasticsearchClient } from 'kibana/server';
-
-import { Mappings } from '../modules/types';
-import type { Logger } from '../../../../../src/core/server';
-
-import {
- computeMappingId,
- getIndexExists,
- logMappingDebug,
- logMappingError,
- logMappingInfo,
-} from './utils';
-
-interface CreateMappingOptions {
- esClient: ElasticsearchClient;
- mappings: Mappings[];
- prefix: string;
- suffix: string;
- logger: Logger;
- kibanaVersion: string;
-}
-
-export const installMappings = async ({
- esClient,
- kibanaVersion,
- mappings,
- prefix,
- suffix,
- logger,
-}: CreateMappingOptions): Promise => {
- for (const mapping of mappings) {
- const { index } = mapping.mappings._meta;
- const mappingId = computeMappingId({ id: index, prefix, suffix });
- const exists = await getIndexExists(esClient, mappingId);
- const computedBody = {
- ...mapping,
- ...{
- mappings: {
- ...mapping.mappings,
- _meta: {
- ...mapping.mappings._meta,
- ...{
- created_by: 'metrics_entities',
- index: mappingId,
- version: kibanaVersion,
- },
- },
- },
- },
- };
- if (!exists) {
- try {
- logMappingInfo({ id: mappingId, logger, message: 'does not exist, creating the mapping' });
- await esClient.indices.create({
- body: computedBody,
- index: mappingId,
- });
- } catch (error) {
- logMappingError({
- error,
- id: mappingId,
- logger,
- message: 'cannot install mapping',
- postBody: computedBody,
- });
- }
- } else {
- logMappingDebug({
- id: mappingId,
- logger,
- message: 'mapping already exists. It will not be recreated',
- });
- }
- }
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/install_transforms.ts b/x-pack/plugins/metrics_entities/server/services/install_transforms.ts
deleted file mode 100644
index eec4f8d555356..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/install_transforms.ts
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ElasticsearchClient } from 'kibana/server';
-
-import { Transforms } from '../modules/types';
-import type { Logger } from '../../../../../src/core/server';
-
-import {
- computeMappingId,
- computeTransformId,
- getTransformExists,
- logTransformDebug,
- logTransformError,
- logTransformInfo,
-} from './utils';
-
-interface CreateTransformOptions {
- esClient: ElasticsearchClient;
- transforms: Transforms[];
- autoStart: boolean;
- indices: string[];
- frequency: string;
- logger: Logger;
- query: object;
- docsPerSecond: number | undefined;
- maxPageSearchSize: number;
- sync: {
- time: {
- delay: string;
- field: string;
- };
- };
- prefix: string;
- suffix: string;
-}
-
-export const installTransforms = async ({
- autoStart,
- esClient,
- frequency,
- indices,
- docsPerSecond,
- logger,
- maxPageSearchSize,
- prefix,
- suffix,
- transforms,
- query,
- sync,
-}: CreateTransformOptions): Promise => {
- for (const transform of transforms) {
- const destIndex = transform?.dest?.index ?? transform.id;
- const computedMappingIndex = computeMappingId({ id: destIndex, prefix, suffix });
- const { id, ...transformNoId } = {
- ...transform,
- ...{ source: { ...transform.source, index: indices, query } },
- ...{ dest: { ...transform.dest, index: computedMappingIndex } },
- ...{
- settings: {
- ...transform.settings,
- docs_per_second: docsPerSecond,
- max_page_search_size: maxPageSearchSize,
- },
- },
- frequency,
- sync,
- };
-
- const computedName = computeTransformId({ id, prefix, suffix });
- const exists = await getTransformExists(esClient, computedName);
- if (!exists) {
- try {
- logTransformInfo({
- id: computedName,
- logger,
- message: 'does not exist, creating the transform',
- });
- await esClient.transform.putTransform({
- body: transformNoId,
- defer_validation: true,
- transform_id: computedName,
- });
-
- if (autoStart) {
- logTransformInfo({
- id: computedName,
- logger,
- message: 'is being auto started',
- });
- await esClient.transform.startTransform({
- transform_id: computedName,
- });
- } else {
- logTransformInfo({
- id: computedName,
- logger,
- message: 'is not being auto started',
- });
- }
- } catch (error) {
- logTransformError({
- error,
- id: computedName,
- logger,
- message: 'Could not create and/or start',
- postBody: transformNoId,
- });
- }
- } else {
- logTransformDebug({
- id: computedName,
- logger,
- message: 'already exists. It will not be recreated',
- });
- }
- }
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/metrics_entities_client.ts b/x-pack/plugins/metrics_entities/server/services/metrics_entities_client.ts
deleted file mode 100644
index 3905503df876d..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/metrics_entities_client.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ElasticsearchClient } from 'kibana/server';
-
-import type { Logger } from '../../../../../src/core/server';
-
-import { getTransforms } from './get_transforms';
-import {
- ConstructorOptions,
- DeleteTransformsOptions,
- PostTransformsOptions,
-} from './metrics_entities_client_types';
-import { postTransforms } from './post_transforms';
-import { deleteTransforms } from './delete_transforms';
-
-export class MetricsEntitiesClient {
- private readonly esClient: ElasticsearchClient;
- private readonly logger: Logger;
- private readonly kibanaVersion: string;
-
- constructor({ esClient, logger, kibanaVersion }: ConstructorOptions) {
- this.esClient = esClient;
- this.logger = logger;
- this.kibanaVersion = kibanaVersion;
- }
-
- // TODO: Type the unknown to be stronger
- public getTransforms = async (): Promise => {
- const { esClient, logger } = this;
- return getTransforms({ esClient, logger });
- };
-
- public postTransforms = async ({
- autoStart,
- frequency,
- docsPerSecond,
- maxPageSearchSize,
- modules,
- indices,
- prefix,
- suffix,
- query,
- sync,
- }: PostTransformsOptions): Promise => {
- const { esClient, logger, kibanaVersion } = this;
- return postTransforms({
- autoStart,
- docsPerSecond,
- esClient,
- frequency,
- indices,
- kibanaVersion,
- logger,
- maxPageSearchSize,
- modules,
- prefix,
- query,
- suffix,
- sync,
- });
- };
-
- public deleteTransforms = async ({
- modules,
- prefix,
- suffix,
- }: DeleteTransformsOptions): Promise => {
- const { esClient, logger } = this;
- return deleteTransforms({ esClient, logger, modules, prefix, suffix });
- };
-}
diff --git a/x-pack/plugins/metrics_entities/server/services/metrics_entities_client_types.ts b/x-pack/plugins/metrics_entities/server/services/metrics_entities_client_types.ts
deleted file mode 100644
index def26c5342ef9..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/metrics_entities_client_types.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ElasticsearchClient } from 'kibana/server';
-
-import type { Logger } from '../../../../../src/core/server';
-import { ModuleNames } from '../modules';
-
-export interface ConstructorOptions {
- esClient: ElasticsearchClient;
- logger: Logger;
- kibanaVersion: string;
-}
-
-export interface PostTransformsOptions {
- modules: ModuleNames[];
- autoStart: boolean;
- frequency: string;
- indices: string[];
- docsPerSecond: number | undefined;
- maxPageSearchSize: number;
- prefix: string;
- query: object;
- suffix: string;
- sync: {
- time: {
- delay: string;
- field: string;
- };
- };
-}
-
-export interface DeleteTransformsOptions {
- modules: ModuleNames[];
- prefix: string;
- suffix: string;
-}
diff --git a/x-pack/plugins/metrics_entities/server/services/post_transforms.ts b/x-pack/plugins/metrics_entities/server/services/post_transforms.ts
deleted file mode 100644
index f14f53d78f10e..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/post_transforms.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ElasticsearchClient } from 'kibana/server';
-
-import { ModuleNames, installableMappings, installableTransforms } from '../modules';
-import type { Logger } from '../../../../../src/core/server';
-
-import { installMappings } from './install_mappings';
-import { installTransforms } from './install_transforms';
-
-interface PostTransformsOptions {
- logger: Logger;
- esClient: ElasticsearchClient;
- modules: ModuleNames[];
- autoStart: boolean;
- frequency: string;
- indices: string[];
- docsPerSecond: number | undefined;
- kibanaVersion: string;
- maxPageSearchSize: number;
- query: object;
- prefix: string;
- suffix: string;
- sync: {
- time: {
- delay: string;
- field: string;
- };
- };
-}
-
-export const postTransforms = async ({
- autoStart,
- logger,
- esClient,
- frequency,
- indices,
- docsPerSecond,
- kibanaVersion,
- maxPageSearchSize,
- modules,
- prefix,
- suffix,
- query,
- sync,
-}: PostTransformsOptions): Promise => {
- for (const moduleName of modules) {
- const mappings = installableMappings[moduleName];
- const transforms = installableTransforms[moduleName];
-
- await installMappings({ esClient, kibanaVersion, logger, mappings, prefix, suffix });
- await installTransforms({
- autoStart,
- docsPerSecond,
- esClient,
- frequency,
- indices,
- logger,
- maxPageSearchSize,
- prefix,
- query,
- suffix,
- sync,
- transforms,
- });
- }
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/stop_transforms.ts b/x-pack/plugins/metrics_entities/server/services/stop_transforms.ts
deleted file mode 100644
index 18476d8345cf2..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/stop_transforms.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-// TODO: Write this
diff --git a/x-pack/plugins/metrics_entities/server/services/uninstall_mappings.ts b/x-pack/plugins/metrics_entities/server/services/uninstall_mappings.ts
deleted file mode 100644
index b2ea9d96cda13..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/uninstall_mappings.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ElasticsearchClient } from 'kibana/server';
-
-import { Mappings } from '../modules/types';
-import type { Logger } from '../../../../../src/core/server';
-
-import { computeMappingId, logMappingInfo } from './utils';
-import { logMappingError } from './utils/log_mapping_error';
-
-interface UninstallMappingOptions {
- esClient: ElasticsearchClient;
- mappings: Mappings[];
- prefix: string;
- suffix: string;
- logger: Logger;
-}
-
-export const uninstallMappings = async ({
- esClient,
- logger,
- mappings,
- prefix,
- suffix,
-}: UninstallMappingOptions): Promise => {
- const indices = mappings.map((mapping) => {
- const { index } = mapping.mappings._meta;
- return computeMappingId({ id: index, prefix, suffix });
- });
- logMappingInfo({
- id: indices.join(),
- logger,
- message: 'deleting indices',
- });
- try {
- await esClient.indices.delete({
- allow_no_indices: true,
- ignore_unavailable: true,
- index: indices,
- });
- } catch (error) {
- logMappingError({
- error,
- id: indices.join(),
- logger,
- message: 'could not delete index',
- postBody: undefined,
- });
- }
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/uninstall_transforms.ts b/x-pack/plugins/metrics_entities/server/services/uninstall_transforms.ts
deleted file mode 100644
index fbf59fc28af2f..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/uninstall_transforms.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ElasticsearchClient } from 'kibana/server';
-import { asyncForEach } from '@kbn/std';
-
-import { Transforms } from '../modules/types';
-import type { Logger } from '../../../../../src/core/server';
-
-import {
- computeTransformId,
- getTransformExists,
- logTransformError,
- logTransformInfo,
-} from './utils';
-
-interface UninstallTransformsOptions {
- esClient: ElasticsearchClient;
- transforms: Transforms[];
- prefix: string;
- suffix: string;
- logger: Logger;
-}
-
-/**
- * Uninstalls all the transforms underneath a given module
- */
-export const uninstallTransforms = async ({
- esClient,
- logger,
- prefix,
- suffix,
- transforms,
-}: UninstallTransformsOptions): Promise => {
- await asyncForEach(transforms, async (transform) => {
- const { id } = transform;
- const computedId = computeTransformId({ id, prefix, suffix });
- const exists = await getTransformExists(esClient, computedId);
- if (exists) {
- logTransformInfo({
- id: computedId,
- logger,
- message: 'stopping transform',
- });
- try {
- await esClient.transform.stopTransform({
- allow_no_match: true,
- force: true,
- timeout: '5s',
- transform_id: computedId,
- wait_for_completion: true,
- });
- } catch (error) {
- logTransformError({
- error,
- id: computedId,
- logger,
- message: 'Could not stop transform, still attempting to delete it',
- postBody: undefined,
- });
- }
- logTransformInfo({
- id: computedId,
- logger,
- message: 'deleting transform',
- });
- try {
- await esClient.transform.deleteTransform({
- force: true,
- transform_id: computedId,
- });
- } catch (error) {
- logTransformError({
- error,
- id: computedId,
- logger,
- message: 'Could not create and/or start',
- postBody: undefined,
- });
- }
- } else {
- logTransformInfo({
- id: computedId,
- logger,
- message: 'transform does not exist to delete',
- });
- }
- });
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/utils/compute_mapping_index.ts b/x-pack/plugins/metrics_entities/server/services/utils/compute_mapping_index.ts
deleted file mode 100644
index bb1a7720fc575..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/utils/compute_mapping_index.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { computeTransformId } from './compute_transform_id';
-
-export const computeMappingId = ({
- prefix,
- id,
- suffix,
-}: {
- prefix: string;
- id: string;
- suffix: string;
-}): string => {
- // TODO: This causes issues if above 65 character limit. We should limit the prefix
- // and anything else on the incoming routes to avoid this causing an issue. We should still
- // throw here in case I change the prefix or other names and cause issues.
- const computedId = computeTransformId({ id, prefix, suffix });
- return `.${computedId}`;
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/utils/compute_transform_id.ts b/x-pack/plugins/metrics_entities/server/services/utils/compute_transform_id.ts
deleted file mode 100644
index dde4d98220549..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/utils/compute_transform_id.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ELASTIC_NAME } from '../../../common/constants';
-
-export const computeTransformId = ({
- prefix,
- id,
- suffix,
-}: {
- prefix: string;
- id: string;
- suffix: string;
-}): string => {
- const prefixExists = prefix.trim() !== '';
- const suffixExists = suffix.trim() !== '';
-
- // TODO: Check for invalid characters on the main route for prefixExists and suffixExists and do an invalidation
- // if either have invalid characters for a job name. Might want to add that same check within the API too at a top level?
- if (prefixExists && suffixExists) {
- return `${ELASTIC_NAME}_${prefix}_${id}_${suffix}`;
- } else if (prefixExists) {
- return `${ELASTIC_NAME}_${prefix}_${id}`;
- } else if (suffixExists) {
- return `${ELASTIC_NAME}_${id}_${suffix}`;
- } else {
- return `${ELASTIC_NAME}_${id}`;
- }
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/utils/get_index_exists.ts b/x-pack/plugins/metrics_entities/server/services/utils/get_index_exists.ts
deleted file mode 100644
index 7bac15d516221..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/utils/get_index_exists.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ElasticsearchClient } from 'kibana/server';
-
-/**
- * Tried and true, copied forever again and again, the way we check if an index exists
- * with the least amount of privileges.
- * @param esClient The client to check if the index already exists
- * @param index The index to check for
- * @returns true if it exists, otherwise false
- */
-export const getIndexExists = async (
- esClient: ElasticsearchClient,
- index: string
-): Promise => {
- try {
- const response = await esClient.search({
- allow_no_indices: true,
- body: {
- terminate_after: 1,
- },
- index,
- size: 0,
- });
- return response._shards.total > 0;
- } catch (err) {
- if (err.body?.status === 404) {
- return false;
- } else {
- throw err.body ? err.body : err;
- }
- }
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/utils/get_json.ts b/x-pack/plugins/metrics_entities/server/services/utils/get_json.ts
deleted file mode 100644
index 71853f2a4ee66..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/utils/get_json.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-// TODO: Move indent to configuration part or flip to default false
-export const getJSON = (body: unknown, indent: boolean = true): string =>
- indent ? JSON.stringify(body, null, 2) : JSON.stringify(body);
diff --git a/x-pack/plugins/metrics_entities/server/services/utils/get_transform_exists.ts b/x-pack/plugins/metrics_entities/server/services/utils/get_transform_exists.ts
deleted file mode 100644
index f6b9266baca91..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/utils/get_transform_exists.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ElasticsearchClient } from 'kibana/server';
-
-export const getTransformExists = async (
- esClient: ElasticsearchClient,
- id: string
-): Promise => {
- try {
- const { count } = await esClient.transform.getTransform({
- size: 1000,
- transform_id: id,
- });
- return count > 0;
- } catch (err) {
- if (err.body?.status === 404) {
- return false;
- } else {
- throw err.body ? err.body : err;
- }
- }
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/utils/index.ts b/x-pack/plugins/metrics_entities/server/services/utils/index.ts
deleted file mode 100644
index 0871c1bf3f7b4..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/utils/index.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-export * from './compute_mapping_index';
-export * from './compute_transform_id';
-export * from './get_index_exists';
-export * from './get_transform_exists';
-export * from './log_mapping_debug';
-export * from './log_mapping_error';
-export * from './log_mapping_info';
-export * from './log_transform_debug';
-export * from './log_transform_error';
-export * from './log_transform_info';
diff --git a/x-pack/plugins/metrics_entities/server/services/utils/log_mapping_debug.ts b/x-pack/plugins/metrics_entities/server/services/utils/log_mapping_debug.ts
deleted file mode 100644
index f3c56aac900f1..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/utils/log_mapping_debug.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import type { Logger } from '../../../../../../src/core/server';
-
-export const logMappingDebug = ({
- logger,
- id,
- message,
-}: {
- logger: Logger;
- id: string;
- message: string;
-}): void => {
- logger.debug(`mapping id: "${id}", ${message}`);
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/utils/log_mapping_error.ts b/x-pack/plugins/metrics_entities/server/services/utils/log_mapping_error.ts
deleted file mode 100644
index 43ae07619318c..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/utils/log_mapping_error.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import type { Logger } from '../../../../../../src/core/server';
-
-import { getJSON } from './get_json';
-
-export const logMappingError = ({
- logger,
- id,
- message,
- error,
- postBody,
-}: {
- logger: Logger;
- id: string;
- error: unknown;
- message: string;
- postBody: {} | undefined;
-}): void => {
- const postString = postBody != null ? `, post body: "${getJSON(postBody)}"` : '';
- logger.error(`${message}, mapping id: "${id}"${postString}, error: ${getJSON(error)}`);
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/utils/log_mapping_info.ts b/x-pack/plugins/metrics_entities/server/services/utils/log_mapping_info.ts
deleted file mode 100644
index e75c380aad38a..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/utils/log_mapping_info.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import type { Logger } from '../../../../../../src/core/server';
-
-export const logMappingInfo = ({
- logger,
- id,
- message,
-}: {
- logger: Logger;
- id: string;
- message: string;
-}): void => {
- logger.info(`mapping id: "${id}", ${message}`);
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/utils/log_transform_debug.ts b/x-pack/plugins/metrics_entities/server/services/utils/log_transform_debug.ts
deleted file mode 100644
index 61c5dd0b37947..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/utils/log_transform_debug.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import type { Logger } from '../../../../../../src/core/server';
-
-export const logTransformDebug = ({
- logger,
- id,
- message,
-}: {
- logger: Logger;
- id: string;
- message: string;
-}): void => {
- logger.debug(`transform id: "${id}", ${message}`);
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/utils/log_transform_error.ts b/x-pack/plugins/metrics_entities/server/services/utils/log_transform_error.ts
deleted file mode 100644
index 2d883ca68be75..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/utils/log_transform_error.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import type { Logger } from '../../../../../../src/core/server';
-
-import { getJSON } from './get_json';
-
-export const logTransformError = ({
- id,
- logger,
- error,
- postBody,
- message,
-}: {
- logger: Logger;
- id: string;
- error: unknown;
- message: string;
- postBody: {} | undefined;
-}): void => {
- const postString = postBody != null ? `, post body: "${getJSON(postBody)}"` : '';
- logger.error(`${message}, transform id: ${id}${postString}, response error: ${getJSON(error)}`);
-};
diff --git a/x-pack/plugins/metrics_entities/server/services/utils/log_transform_info.ts b/x-pack/plugins/metrics_entities/server/services/utils/log_transform_info.ts
deleted file mode 100644
index 1bfb918664007..0000000000000
--- a/x-pack/plugins/metrics_entities/server/services/utils/log_transform_info.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import type { Logger } from '../../../../../../src/core/server';
-
-export const logTransformInfo = ({
- logger,
- id,
- message,
-}: {
- logger: Logger;
- id: string;
- message: string;
-}): void => {
- logger.info(`transform id: "${id}", ${message}`);
-};
diff --git a/x-pack/plugins/metrics_entities/server/types.ts b/x-pack/plugins/metrics_entities/server/types.ts
deleted file mode 100644
index 41df562234c0d..0000000000000
--- a/x-pack/plugins/metrics_entities/server/types.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ElasticsearchClient, IContextProvider, RequestHandlerContext } from 'kibana/server';
-
-import { MetricsEntitiesClient } from './services/metrics_entities_client';
-
-export type GetMetricsEntitiesClientType = (esClient: ElasticsearchClient) => MetricsEntitiesClient;
-
-export interface MetricsEntitiesPluginSetup {
- getMetricsEntitiesClient: GetMetricsEntitiesClientType;
-}
-
-export type MetricsEntitiesPluginStart = void;
-
-export type ContextProvider = IContextProvider<
- MetricsEntitiesRequestHandlerContext,
- 'metricsEntities'
->;
-
-export interface MetricsEntitiesApiRequestHandlerContext {
- getMetricsEntitiesClient: () => MetricsEntitiesClient;
-}
-
-export interface MetricsEntitiesRequestHandlerContext extends RequestHandlerContext {
- metricsEntities?: MetricsEntitiesApiRequestHandlerContext;
-}
-
-/**
- * @internal
- */
-export type ContextProviderReturn = Promise;
diff --git a/x-pack/plugins/metrics_entities/tsconfig.json b/x-pack/plugins/metrics_entities/tsconfig.json
deleted file mode 100644
index 402b327a2dbf2..0000000000000
--- a/x-pack/plugins/metrics_entities/tsconfig.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "extends": "../../../tsconfig.base.json",
- "compilerOptions": {
- "outDir": "./target/types",
- "emitDeclarationOnly": true,
- "declaration": true,
- "declarationMap": true
- },
- "include": [
- "common/**/*",
- "public/**/*",
- "server/**/*",
- // have to declare *.json explicitly due to https://github.com/microsoft/TypeScript/issues/25636
- "server/**/*.json",
- "../../../typings/**/*"
- ],
- "references": [
- { "path": "../../../src/core/tsconfig.json" },
- { "path": "../spaces/tsconfig.json" },
- { "path": "../security/tsconfig.json" },
- { "path": "../licensing/tsconfig.json" },
- { "path": "../features/tsconfig.json" },
- { "path": "../../../src/plugins/usage_collection/tsconfig.json" },
- { "path": "../../../src/plugins/kibana_utils/tsconfig.json" }
- ]
-}
diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts
index f7bdc889f9c33..3b820b16ef8a4 100644
--- a/x-pack/plugins/security_solution/common/constants.ts
+++ b/x-pack/plugins/security_solution/common/constants.ts
@@ -5,8 +5,6 @@
* 2.0.
*/
-import type { TransformConfigSchema } from './transforms/types';
-
/**
* as const
*
@@ -54,7 +52,6 @@ export const DEFAULT_INTERVAL_PAUSE = true as const;
export const DEFAULT_INTERVAL_TYPE = 'manual' as const;
export const DEFAULT_INTERVAL_VALUE = 300000 as const; // ms
export const DEFAULT_TIMEPICKER_QUICK_RANGES = 'timepicker:quickRanges' as const;
-export const DEFAULT_TRANSFORMS = 'securitySolution:transforms' as const;
export const SCROLLING_DISABLED_CLASS_NAME = 'scrolling-disabled' as const;
export const GLOBAL_HEADER_HEIGHT = 96 as const; // px
export const FILTERS_GLOBAL_HEIGHT = 109 as const; // px
@@ -203,38 +200,6 @@ export const IP_REPUTATION_LINKS_SETTING_DEFAULT = `[
{ "name": "talosIntelligence.com", "url_template": "https://talosintelligence.com/reputation_center/lookup?search={{ip}}" }
]`;
-/** The default settings for the transforms */
-export const defaultTransformsSetting: TransformConfigSchema = {
- enabled: false,
- auto_start: true,
- auto_create: true,
- query: {
- range: {
- '@timestamp': {
- gte: 'now-1d/d',
- format: 'strict_date_optional_time',
- },
- },
- },
- retention_policy: {
- time: {
- field: '@timestamp',
- max_age: '1w',
- },
- },
- max_page_search_size: 5000,
- settings: [
- {
- prefix: 'all',
- indices: ['auditbeat-*', 'endgame-*', 'filebeat-*', 'logs-*', 'packetbeat-*', 'winlogbeat-*'],
- data_sources: [
- ['auditbeat-*', 'endgame-*', 'filebeat-*', 'logs-*', 'packetbeat-*', 'winlogbeat-*'],
- ],
- },
- ],
-};
-export const DEFAULT_TRANSFORMS_SETTING = JSON.stringify(defaultTransformsSetting, null, 2);
-
/**
* Id for the notifications alerting type
* @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function
@@ -371,13 +336,6 @@ export const showAllOthersBucket: string[] = [
'user.name',
];
-/**
- * Used for transforms for metrics_entities. If the security_solutions pulls in
- * the metrics_entities plugin, then it should pull this constant from there rather
- * than use it from here.
- */
-export const ELASTIC_NAME = 'estc' as const;
-
export const RISKY_HOSTS_INDEX_PREFIX = 'ml_host_risk_score_' as const;
export const RISKY_USERS_INDEX_PREFIX = 'ml_user_risk_score_' as const;
diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts
index a9cf3e4a8132e..374901358650e 100644
--- a/x-pack/plugins/security_solution/common/experimental_features.ts
+++ b/x-pack/plugins/security_solution/common/experimental_features.ts
@@ -12,7 +12,6 @@ export type ExperimentalFeatures = typeof allowedExperimentalValues;
* This object is then used to validate and parse the value entered.
*/
export const allowedExperimentalValues = Object.freeze({
- metricsEntitiesEnabled: false,
ruleRegistryEnabled: true,
tGridEnabled: true,
tGridEventRenderedViewEnabled: true,
diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/index.ts
index 245abdd49a62d..5473349bf144b 100644
--- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/index.ts
+++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/index.ts
@@ -17,7 +17,6 @@ export enum HostsQueries {
details = 'hostDetails',
firstOrLastSeen = 'firstOrLastSeen',
hosts = 'hosts',
- hostsEntities = 'hostsEntities',
overview = 'overviewHost',
uncommonProcesses = 'uncommonProcesses',
}
diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/authentications/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/authentications/index.ts
index 73729b613c38c..b120161210745 100644
--- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/authentications/index.ts
+++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/authentications/index.ts
@@ -12,8 +12,6 @@ import { HostsKpiHistogramData } from '../common';
export interface HostsKpiAuthenticationsHistogramCount {
doc_count: number;
- // TODO: Should I keep this or split this interface into two for entities and non-entities?
- value?: number;
}
export type HostsKpiAuthenticationsRequestOptions = RequestBasicOptions;
diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/index.ts
index d48172bebee4c..79054fc736a80 100644
--- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/index.ts
+++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/index.ts
@@ -16,11 +16,8 @@ import { HostsKpiUniqueIpsStrategyResponse } from './unique_ips';
export enum HostsKpiQueries {
kpiAuthentications = 'hostsKpiAuthentications',
- kpiAuthenticationsEntities = 'hostsKpiAuthenticationsEntities',
kpiHosts = 'hostsKpiHosts',
- kpiHostsEntities = 'hostsKpiHostsEntities',
kpiUniqueIps = 'hostsKpiUniqueIps',
- kpiUniqueIpsEntities = 'hostsKpiUniqueIpsEntities',
}
export type HostsKpiStrategyResponse =
diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/index.ts
index e59aec9e000d9..f2d9e0e36bd0e 100644
--- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/index.ts
+++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/index.ts
@@ -59,7 +59,6 @@ import {
} from './network';
import {
MatrixHistogramQuery,
- MatrixHistogramQueryEntities,
MatrixHistogramRequestOptions,
MatrixHistogramStrategyResponse,
} from './matrix_histogram';
@@ -106,8 +105,7 @@ export type FactoryQueryTypes =
| NetworkKpiQueries
| RiskQueries
| CtiQueries
- | typeof MatrixHistogramQuery
- | typeof MatrixHistogramQueryEntities;
+ | typeof MatrixHistogramQuery;
export interface RequestBasicOptions extends IEsSearchRequest {
timerange: TimerangeInput;
diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/index.ts
index ef637031dd899..d1d9a8f5d9d3e 100644
--- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/index.ts
+++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/index.ts
@@ -25,11 +25,9 @@ export * from './events';
export * from './preview';
export const MatrixHistogramQuery = 'matrixHistogram';
-export const MatrixHistogramQueryEntities = 'matrixHistogramEntities';
export enum MatrixHistogramType {
authentications = 'authentications',
- authenticationsEntities = 'authenticationsEntities',
anomalies = 'anomalies',
events = 'events',
alerts = 'alerts',
@@ -41,7 +39,6 @@ export const MatrixHistogramTypeToAggName = {
[MatrixHistogramType.alerts]: 'aggregations.alertsGroup.buckets',
[MatrixHistogramType.anomalies]: 'aggregations.anomalyActionGroup.buckets',
[MatrixHistogramType.authentications]: 'aggregations.eventActionGroup.buckets',
- [MatrixHistogramType.authenticationsEntities]: 'aggregations.events.buckets',
[MatrixHistogramType.dns]: 'aggregations.dns_name_query_count.buckets',
[MatrixHistogramType.events]: 'aggregations.eventActionGroup.buckets',
[MatrixHistogramType.preview]: 'aggregations.preview.buckets',
diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/index.ts
index 2e0a5d7d2f0f1..24c6484f94e71 100644
--- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/index.ts
+++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/index.ts
@@ -23,8 +23,6 @@ export enum NetworkQueries {
overview = 'overviewNetwork',
tls = 'tls',
topCountries = 'topCountries',
- topCountriesEntities = 'topCountriesEntities',
topNFlow = 'topNFlow',
- topNFlowEntities = 'topNFlowEntities',
users = 'users',
}
diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/index.ts
index cb18a3edb4937..fa9e55096f7a6 100644
--- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/index.ts
+++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/index.ts
@@ -19,14 +19,10 @@ import { NetworkKpiUniquePrivateIpsStrategyResponse } from './unique_private_ips
export enum NetworkKpiQueries {
dns = 'networkKpiDns',
- dnsEntities = 'networkKpiDnsEntities',
networkEvents = 'networkKpiNetworkEvents',
- networkEventsEntities = 'networkKpiNetworkEventsEntities',
tlsHandshakes = 'networkKpiTlsHandshakes',
- tlsHandshakesEntities = 'networkKpiTlsHandshakesEntities',
uniqueFlows = 'networkKpiUniqueFlows',
uniquePrivateIps = 'networkKpiUniquePrivateIps',
- uniquePrivateIpsEntities = 'networkKpiUniquePrivateIpsEntities',
}
export type NetworkKpiStrategyResponse =
diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/authentications/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/authentications/index.ts
index 205169c8e6b0e..f4b6cdcbe6e55 100644
--- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/authentications/index.ts
+++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/authentications/index.ts
@@ -76,13 +76,9 @@ export interface AuthenticationBucket {
doc_count: number;
failures: {
doc_count: number;
- // TODO: Keep this or make a new structure?
- value?: number;
};
successes: {
doc_count: number;
- // TODO: Keep this or make a new structure?
- value?: number;
};
authentication: {
hits: {
diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/index.ts
index 7b3937de2913e..4223b9b2fa7ab 100644
--- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/index.ts
+++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/index.ts
@@ -18,7 +18,6 @@ export enum UsersQueries {
kpiTotalUsers = 'usersKpiTotalUsers',
users = 'allUsers',
authentications = 'authentications',
- authenticationsEntities = 'authenticationsEntities',
}
export type UserskKpiStrategyResponse = Omit;
diff --git a/x-pack/plugins/security_solution/common/transforms/types.ts b/x-pack/plugins/security_solution/common/transforms/types.ts
deleted file mode 100644
index ac4e3cae92e22..0000000000000
--- a/x-pack/plugins/security_solution/common/transforms/types.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { schema, TypeOf } from '@kbn/config-schema';
-
-/**
- * Kibana configuration schema
- */
-export const transformConfigSchema = schema.object({
- auto_start: schema.boolean(),
- auto_create: schema.boolean(),
- enabled: schema.boolean(),
- query: schema.maybe(schema.object({}, { unknowns: 'allow' })),
- retention_policy: schema.maybe(
- schema.object({
- time: schema.object({
- field: schema.string(),
- max_age: schema.string(),
- }),
- })
- ),
- docs_per_second: schema.maybe(schema.number({ min: 1 })),
- max_page_search_size: schema.maybe(schema.number({ min: 1, max: 10000 })),
- settings: schema.arrayOf(
- schema.object({
- prefix: schema.string(),
- indices: schema.arrayOf(schema.string()),
- data_sources: schema.arrayOf(schema.arrayOf(schema.string())),
- disable_widgets: schema.maybe(schema.arrayOf(schema.string())),
- disable_transforms: schema.maybe(schema.arrayOf(schema.string())),
- })
- ),
-});
-
-export type TransformConfigSchema = TypeOf;
diff --git a/x-pack/plugins/security_solution/public/common/containers/authentications/index.tsx b/x-pack/plugins/security_solution/public/common/containers/authentications/index.tsx
index 593d5e4186e29..543ebc3e15e9a 100644
--- a/x-pack/plugins/security_solution/public/common/containers/authentications/index.tsx
+++ b/x-pack/plugins/security_solution/public/common/containers/authentications/index.tsx
@@ -29,7 +29,6 @@ import { getInspectResponse } from '../../../helpers';
import { InspectResponse } from '../../../types';
import * as i18n from './translations';
-import { useTransforms } from '../../../transforms/containers/use_transforms';
import { useAppToasts } from '../../../common/hooks/use_app_toasts';
export interface AuthenticationArgs {
@@ -73,7 +72,6 @@ export const useAuthentications = ({
const [loading, setLoading] = useState(false);
const [authenticationsRequest, setAuthenticationsRequest] =
useState(null);
- const { getTransformChangesIfTheyExist } = useTransforms();
const { addError, addWarning } = useAppToasts();
const wrappedLoadMore = useCallback(
@@ -162,26 +160,19 @@ export const useAuthentications = ({
useEffect(() => {
setAuthenticationsRequest((prevRequest) => {
- const { indices, factoryQueryType, timerange } = getTransformChangesIfTheyExist({
- factoryQueryType: UsersQueries.authentications,
- indices: indexNames,
- filterQuery,
- timerange: {
- interval: '12h',
- from: startDate,
- to: endDate,
- },
- });
-
const myRequest = {
...(prevRequest ?? {}),
- defaultIndex: indices,
+ defaultIndex: indexNames,
docValueFields: docValueFields ?? [],
- factoryQueryType,
+ factoryQueryType: UsersQueries.authentications,
filterQuery: createFilter(filterQuery),
stackByField,
pagination: generateTablePaginationOptions(activePage, limit),
- timerange,
+ timerange: {
+ interval: '12h',
+ from: startDate,
+ to: endDate,
+ },
sort: {} as SortField,
};
if (!deepEqual(prevRequest, myRequest)) {
@@ -198,7 +189,6 @@ export const useAuthentications = ({
stackByField,
limit,
startDate,
- getTransformChangesIfTheyExist,
]);
useEffect(() => {
diff --git a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts
index f6670c98fc0ee..e22960e833b9a 100644
--- a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts
+++ b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts
@@ -25,7 +25,6 @@ import { isErrorResponse, isCompleteResponse } from '../../../../../../../src/pl
import { getInspectResponse } from '../../../helpers';
import { InspectResponse } from '../../../types';
import * as i18n from './translations';
-import { useTransforms } from '../../../transforms/containers/use_transforms';
import { useAppToasts } from '../../hooks/use_app_toasts';
export type Buckets = Array<{
@@ -71,32 +70,18 @@ export const useMatrixHistogram = ({
const abortCtrl = useRef(new AbortController());
const searchSubscription$ = useRef(new Subscription());
const [loading, setLoading] = useState(false);
- const { getTransformChangesIfTheyExist } = useTransforms();
-
- const {
- indices: initialIndexName,
- factoryQueryType: initialFactoryQueryType,
- histogramType: initialHistogramType,
- timerange: initialTimerange,
- } = getTransformChangesIfTheyExist({
- histogramType,
- factoryQueryType: MatrixHistogramQuery,
- indices: indexNames,
- filterQuery,
- timerange: {
- interval: '12h',
- from: startDate,
- to: endDate,
- },
- });
const [matrixHistogramRequest, setMatrixHistogramRequest] =
useState({
- defaultIndex: initialIndexName,
- factoryQueryType: initialFactoryQueryType,
+ defaultIndex: indexNames,
+ factoryQueryType: MatrixHistogramQuery,
filterQuery: createFilter(filterQuery),
- histogramType: initialHistogramType ?? histogramType,
- timerange: initialTimerange,
+ histogramType: histogramType ?? histogramType,
+ timerange: {
+ interval: '12h',
+ from: startDate,
+ to: endDate,
+ },
stackByField,
runtimeMappings,
threshold,
@@ -170,31 +155,17 @@ export const useMatrixHistogram = ({
);
useEffect(() => {
- const {
- indices,
- factoryQueryType,
- histogramType: newHistogramType,
- timerange,
- } = getTransformChangesIfTheyExist({
- histogramType,
- factoryQueryType: MatrixHistogramQuery,
- indices: indexNames,
- filterQuery,
- timerange: {
- interval: '12h',
- from: startDate,
- to: endDate,
- },
- });
-
setMatrixHistogramRequest((prevRequest) => {
const myRequest = {
...prevRequest,
- defaultIndex: indices,
- factoryQueryType,
+ defaultIndex: indexNames,
filterQuery: createFilter(filterQuery),
- histogramType: newHistogramType ?? histogramType,
- timerange,
+ histogramType,
+ timerange: {
+ interval: '12h',
+ from: startDate,
+ to: endDate,
+ },
stackByField,
threshold,
...(isPtrIncluded != null ? { isPtrIncluded } : {}),
@@ -215,7 +186,6 @@ export const useMatrixHistogram = ({
threshold,
isPtrIncluded,
docValueFields,
- getTransformChangesIfTheyExist,
]);
useEffect(() => {
diff --git a/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.test.ts b/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.test.ts
index 131242513e583..ecbf7058fded2 100644
--- a/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.test.ts
+++ b/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.test.ts
@@ -11,12 +11,6 @@ import { act, renderHook } from '@testing-library/react-hooks';
import { useObservable } from '@kbn/securitysolution-hook-utils';
import { FactoryQueryTypes } from '../../../../common/search_strategy';
-jest.mock('../../../transforms/containers/use_transforms', () => ({
- useTransforms: jest.fn(() => ({
- getTransformChangesIfTheyExist: null,
- })),
-}));
-
const mockAddToastError = jest.fn();
jest.mock('../../hooks/use_app_toasts', () => ({
diff --git a/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.tsx b/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.tsx
index 8e284c7c29413..916ed4aad3e47 100644
--- a/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.tsx
+++ b/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.tsx
@@ -25,10 +25,6 @@ import {
isCompleteResponse,
isErrorResponse,
} from '../../../../../../../src/plugins/data/public';
-import {
- TransformChangesIfTheyExist,
- useTransforms,
-} from '../../../transforms/containers/use_transforms';
import { getInspectResponse } from '../../../helpers';
import { inputsModel } from '../../store';
import { useKibana } from '../../lib/kibana';
@@ -39,7 +35,6 @@ type UseSearchStrategyRequestArgs = RequestBasicOptions & {
data: DataPublicPluginStart;
signal: AbortSignal;
factoryQueryType: FactoryQueryTypes;
- getTransformChangesIfTheyExist: TransformChangesIfTheyExist;
};
const search = ({
@@ -49,26 +44,14 @@ const search = ({
defaultIndex,
filterQuery,
timerange,
- getTransformChangesIfTheyExist,
...requestProps
}: UseSearchStrategyRequestArgs): Observable => {
- const {
- indices: transformIndices,
- factoryQueryType: transformFactoryQueryType,
- timerange: transformTimerange,
- } = getTransformChangesIfTheyExist({
- factoryQueryType,
- indices: defaultIndex,
- filterQuery,
- timerange,
- });
-
return data.search.search(
{
...requestProps,
- factoryQueryType: transformFactoryQueryType,
- defaultIndex: transformIndices,
- timerange: transformTimerange,
+ factoryQueryType,
+ defaultIndex,
+ timerange,
filterQuery,
},
{
@@ -114,7 +97,6 @@ export const useSearchStrategy = ({
abort?: boolean;
}) => {
const abortCtrl = useRef(new AbortController());
- const { getTransformChangesIfTheyExist } = useTransforms();
const refetch = useRef(noop);
const { data } = useKibana().services;
@@ -141,7 +123,6 @@ export const useSearchStrategy = ({
...props,
data,
factoryQueryType,
- getTransformChangesIfTheyExist,
signal: abortCtrl.current.signal,
} as never); // This typescast is required because every StrategyRequestType instance has different fields.
};
@@ -151,7 +132,7 @@ export const useSearchStrategy = ({
refetch.current = asyncSearch;
},
- [data, start, factoryQueryType, getTransformChangesIfTheyExist]
+ [data, start, factoryQueryType]
);
useEffect(() => {
diff --git a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts
index b683f4bd1375a..a0053bba304cc 100644
--- a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts
+++ b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts
@@ -32,7 +32,6 @@ import {
DEFAULT_RULES_TABLE_REFRESH_SETTING,
DEFAULT_RULE_REFRESH_INTERVAL_ON,
DEFAULT_RULE_REFRESH_INTERVAL_VALUE,
- DEFAULT_TRANSFORMS,
} from '../../../../common/constants';
import { StartServices } from '../../../types';
import { createSecuritySolutionStorageMock } from '../../mock/mock_local_storage';
@@ -61,9 +60,6 @@ const mockUiSettings: Record = {
on: DEFAULT_RULE_REFRESH_INTERVAL_ON,
value: DEFAULT_RULE_REFRESH_INTERVAL_VALUE,
},
- [DEFAULT_TRANSFORMS]: {
- enabled: false,
- },
};
export const createUseUiSettingMock =
diff --git a/x-pack/plugins/security_solution/public/detections/components/user_info/index.tsx b/x-pack/plugins/security_solution/public/detections/components/user_info/index.tsx
index 9c81b51445f60..1699d452be1f4 100644
--- a/x-pack/plugins/security_solution/public/detections/components/user_info/index.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/user_info/index.tsx
@@ -10,7 +10,6 @@ import React, { useEffect, useReducer, Dispatch, createContext, useContext } fro
import { useAlertsPrivileges } from '../../containers/detection_engine/alerts/use_alerts_privileges';
import { useSignalIndex } from '../../containers/detection_engine/alerts/use_signal_index';
-import { useCreateTransforms } from '../../../transforms/containers/use_create_transforms';
export interface State {
canUserCRUD: boolean | null;
@@ -233,8 +232,6 @@ export const useUserInfo = (): State => {
createDeSignalIndex: createSignalIndex,
} = useSignalIndex();
- const { createTransforms } = useCreateTransforms();
-
useEffect(() => {
if (!loading && canUserCRUD !== hasKibanaCRUD) {
dispatch({ type: 'updateCanUserCRUD', canUserCRUD: hasKibanaCRUD });
@@ -335,13 +332,6 @@ export const useUserInfo = (): State => {
}
}, [dispatch, loading, signalIndexMappingOutdated, apiSignalIndexMappingOutdated]);
- // TODO: Get the permissions model and if the user has the correct permissions for transforms
- // then activate the transforms similar to the createSignalIndex.
- // TODO: This should move out of detections/components and into its own transform area
- useEffect(() => {
- createTransforms();
- }, [createTransforms]);
-
useEffect(() => {
if (
isAuthenticated &&
diff --git a/x-pack/plugins/security_solution/public/hosts/containers/hosts/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/hosts/index.tsx
index c4259e8a5a737..a951712f97022 100644
--- a/x-pack/plugins/security_solution/public/hosts/containers/hosts/index.tsx
+++ b/x-pack/plugins/security_solution/public/hosts/containers/hosts/index.tsx
@@ -30,7 +30,6 @@ import * as i18n from './translations';
import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/plugins/data/common';
import { getInspectResponse } from '../../../helpers';
import { InspectResponse } from '../../../types';
-import { useTransforms } from '../../../transforms/containers/use_transforms';
import { useAppToasts } from '../../../common/hooks/use_app_toasts';
export const ID = 'hostsAllQuery';
@@ -78,7 +77,6 @@ export const useAllHost = ({
const searchSubscription = useRef(new Subscription());
const [loading, setLoading] = useState(false);
const [hostsRequest, setHostRequest] = useState(null);
- const { getTransformChangesIfTheyExist } = useTransforms();
const { addError, addWarning } = useAppToasts();
const wrappedLoadMore = useCallback(
@@ -168,24 +166,18 @@ export const useAllHost = ({
useEffect(() => {
setHostRequest((prevRequest) => {
- const { indices, factoryQueryType, timerange } = getTransformChangesIfTheyExist({
+ const myRequest = {
+ ...(prevRequest ?? {}),
+ defaultIndex: indexNames,
+ docValueFields: docValueFields ?? [],
factoryQueryType: HostsQueries.hosts,
- indices: indexNames,
- filterQuery,
+ filterQuery: createFilter(filterQuery),
+ pagination: generateTablePaginationOptions(activePage, limit),
timerange: {
interval: '12h',
from: startDate,
to: endDate,
},
- });
- const myRequest = {
- ...(prevRequest ?? {}),
- defaultIndex: indices,
- docValueFields: docValueFields ?? [],
- factoryQueryType,
- filterQuery: createFilter(filterQuery),
- pagination: generateTablePaginationOptions(activePage, limit),
- timerange,
sort: {
direction,
field: sortField,
@@ -206,7 +198,6 @@ export const useAllHost = ({
limit,
startDate,
sortField,
- getTransformChangesIfTheyExist,
]);
useEffect(() => {
diff --git a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/authentications/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/authentications/index.tsx
index 9fa38c14e2ea4..bf67c00c03cd9 100644
--- a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/authentications/index.tsx
+++ b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/authentications/index.tsx
@@ -10,7 +10,6 @@ import { noop } from 'lodash/fp';
import { useCallback, useEffect, useRef, useState } from 'react';
import { Subscription } from 'rxjs';
-import { useTransforms } from '../../../../transforms/containers/use_transforms';
import { useAppToasts } from '../../../../common/hooks/use_app_toasts';
import { inputsModel } from '../../../../common/store';
import { createFilter } from '../../../../common/containers/helpers';
@@ -58,7 +57,6 @@ export const useHostsKpiAuthentications = ({
const [loading, setLoading] = useState(false);
const [hostsKpiAuthenticationsRequest, setHostsKpiAuthenticationsRequest] =
useState(null);
- const { getTransformChangesIfTheyExist } = useTransforms();
const [hostsKpiAuthenticationsResponse, setHostsKpiAuthenticationsResponse] =
useState({
@@ -132,30 +130,24 @@ export const useHostsKpiAuthentications = ({
);
useEffect(() => {
- const { indices, factoryQueryType, timerange } = getTransformChangesIfTheyExist({
- factoryQueryType: HostsKpiQueries.kpiAuthentications,
- indices: indexNames,
- filterQuery,
- timerange: {
- interval: '12h',
- from: startDate,
- to: endDate,
- },
- });
setHostsKpiAuthenticationsRequest((prevRequest) => {
const myRequest = {
...(prevRequest ?? {}),
- defaultIndex: indices,
- factoryQueryType,
+ defaultIndex: indexNames,
+ factoryQueryType: HostsKpiQueries.kpiAuthentications,
filterQuery: createFilter(filterQuery),
- timerange,
+ timerange: {
+ interval: '12h',
+ from: startDate,
+ to: endDate,
+ },
};
if (!deepEqual(prevRequest, myRequest)) {
return myRequest;
}
return prevRequest;
});
- }, [indexNames, endDate, filterQuery, startDate, getTransformChangesIfTheyExist]);
+ }, [indexNames, endDate, filterQuery, startDate]);
useEffect(() => {
hostsKpiAuthenticationsSearch(hostsKpiAuthenticationsRequest);
diff --git a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/hosts/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/hosts/index.tsx
index 63f0476c2b631..a2644277246de 100644
--- a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/hosts/index.tsx
+++ b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/hosts/index.tsx
@@ -10,7 +10,6 @@ import { noop } from 'lodash/fp';
import { useCallback, useEffect, useRef, useState } from 'react';
import { Subscription } from 'rxjs';
-import { useTransforms } from '../../../../transforms/containers/use_transforms';
import { useAppToasts } from '../../../../common/hooks/use_app_toasts';
import { inputsModel } from '../../../../common/store';
import { createFilter } from '../../../../common/containers/helpers';
@@ -57,7 +56,6 @@ export const useHostsKpiHosts = ({
const [loading, setLoading] = useState(false);
const [hostsKpiHostsRequest, setHostsKpiHostsRequest] =
useState(null);
- const { getTransformChangesIfTheyExist } = useTransforms();
const [hostsKpiHostsResponse, setHostsKpiHostsResponse] = useState({
hosts: 0,
@@ -123,29 +121,23 @@ export const useHostsKpiHosts = ({
useEffect(() => {
setHostsKpiHostsRequest((prevRequest) => {
- const { indices, factoryQueryType, timerange } = getTransformChangesIfTheyExist({
+ const myRequest = {
+ ...(prevRequest ?? {}),
+ defaultIndex: indexNames,
factoryQueryType: HostsKpiQueries.kpiHosts,
- indices: indexNames,
- filterQuery,
+ filterQuery: createFilter(filterQuery),
timerange: {
interval: '12h',
from: startDate,
to: endDate,
},
- });
- const myRequest = {
- ...(prevRequest ?? {}),
- defaultIndex: indices,
- factoryQueryType,
- filterQuery: createFilter(filterQuery),
- timerange,
};
if (!deepEqual(prevRequest, myRequest)) {
return myRequest;
}
return prevRequest;
});
- }, [indexNames, endDate, filterQuery, startDate, getTransformChangesIfTheyExist]);
+ }, [indexNames, endDate, filterQuery, startDate]);
useEffect(() => {
hostsKpiHostsSearch(hostsKpiHostsRequest);
diff --git a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/unique_ips/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/unique_ips/index.tsx
index 25a9f76daf40f..24ef95a324b2f 100644
--- a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/unique_ips/index.tsx
+++ b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/unique_ips/index.tsx
@@ -10,7 +10,6 @@ import { noop } from 'lodash/fp';
import { useCallback, useEffect, useRef, useState } from 'react';
import { Subscription } from 'rxjs';
-import { useTransforms } from '../../../../transforms/containers/use_transforms';
import { useAppToasts } from '../../../../common/hooks/use_app_toasts';
import { inputsModel } from '../../../../common/store';
import { createFilter } from '../../../../common/containers/helpers';
@@ -56,7 +55,6 @@ export const useHostsKpiUniqueIps = ({
const abortCtrl = useRef(new AbortController());
const searchSubscription$ = useRef(new Subscription());
const [loading, setLoading] = useState(false);
- const { getTransformChangesIfTheyExist } = useTransforms();
const [hostsKpiUniqueIpsRequest, setHostsKpiUniqueIpsRequest] =
useState(null);
@@ -130,30 +128,24 @@ export const useHostsKpiUniqueIps = ({
);
useEffect(() => {
- const { indices, factoryQueryType, timerange } = getTransformChangesIfTheyExist({
- factoryQueryType: HostsKpiQueries.kpiUniqueIps,
- indices: indexNames,
- filterQuery,
- timerange: {
- interval: '12h',
- from: startDate,
- to: endDate,
- },
- });
setHostsKpiUniqueIpsRequest((prevRequest) => {
const myRequest = {
...(prevRequest ?? {}),
- defaultIndex: indices,
- factoryQueryType,
+ defaultIndex: indexNames,
+ factoryQueryType: HostsKpiQueries.kpiUniqueIps,
filterQuery: createFilter(filterQuery),
- timerange,
+ timerange: {
+ interval: '12h',
+ from: startDate,
+ to: endDate,
+ },
};
if (!deepEqual(prevRequest, myRequest)) {
return myRequest;
}
return prevRequest;
});
- }, [indexNames, endDate, filterQuery, skip, startDate, getTransformChangesIfTheyExist]);
+ }, [indexNames, endDate, filterQuery, skip, startDate]);
useEffect(() => {
hostsKpiUniqueIpsSearch(hostsKpiUniqueIpsRequest);
diff --git a/x-pack/plugins/security_solution/public/network/containers/kpi_network/dns/index.tsx b/x-pack/plugins/security_solution/public/network/containers/kpi_network/dns/index.tsx
index 89f58f547bd75..9e6cf9f620287 100644
--- a/x-pack/plugins/security_solution/public/network/containers/kpi_network/dns/index.tsx
+++ b/x-pack/plugins/security_solution/public/network/containers/kpi_network/dns/index.tsx
@@ -10,7 +10,6 @@ import { noop } from 'lodash/fp';
import { useCallback, useEffect, useRef, useState } from 'react';
import { Subscription } from 'rxjs';
-import { useTransforms } from '../../../../transforms/containers/use_transforms';
import { useAppToasts } from '../../../../common/hooks/use_app_toasts';
import { inputsModel } from '../../../../common/store';
import { createFilter } from '../../../../common/containers/helpers';
@@ -62,7 +61,6 @@ export const useNetworkKpiDns = ({
const [loading, setLoading] = useState(false);
const [networkKpiDnsRequest, setNetworkKpiDnsRequest] =
useState(null);
- const { getTransformChangesIfTheyExist } = useTransforms();
const [networkKpiDnsResponse, setNetworkKpiDnsResponse] = useState({
dnsQueries: 0,
@@ -127,30 +125,23 @@ export const useNetworkKpiDns = ({
useEffect(() => {
setNetworkKpiDnsRequest((prevRequest) => {
- const { indices, factoryQueryType, timerange } = getTransformChangesIfTheyExist({
+ const myRequest = {
+ ...(prevRequest ?? {}),
+ defaultIndex: indexNames,
factoryQueryType: NetworkKpiQueries.dns,
- indices: indexNames,
- filterQuery,
+ filterQuery: createFilter(filterQuery),
timerange: {
interval: '12h',
from: startDate,
to: endDate,
},
- });
-
- const myRequest = {
- ...(prevRequest ?? {}),
- defaultIndex: indices,
- factoryQueryType,
- filterQuery: createFilter(filterQuery),
- timerange,
};
if (!deepEqual(prevRequest, myRequest)) {
return myRequest;
}
return prevRequest;
});
- }, [indexNames, endDate, filterQuery, startDate, getTransformChangesIfTheyExist]);
+ }, [indexNames, endDate, filterQuery, startDate]);
useEffect(() => {
networkKpiDnsSearch(networkKpiDnsRequest);
diff --git a/x-pack/plugins/security_solution/public/network/containers/kpi_network/network_events/index.tsx b/x-pack/plugins/security_solution/public/network/containers/kpi_network/network_events/index.tsx
index 51a5367446b6e..b5c8058f5035c 100644
--- a/x-pack/plugins/security_solution/public/network/containers/kpi_network/network_events/index.tsx
+++ b/x-pack/plugins/security_solution/public/network/containers/kpi_network/network_events/index.tsx
@@ -10,7 +10,6 @@ import { noop } from 'lodash/fp';
import { useCallback, useEffect, useRef, useState } from 'react';
import { Subscription } from 'rxjs';
-import { useTransforms } from '../../../../transforms/containers/use_transforms';
import { useAppToasts } from '../../../../common/hooks/use_app_toasts';
import { inputsModel } from '../../../../common/store';
import { createFilter } from '../../../../common/containers/helpers';
@@ -62,7 +61,6 @@ export const useNetworkKpiNetworkEvents = ({
const [loading, setLoading] = useState(false);
const [networkKpiNetworkEventsRequest, setNetworkKpiNetworkEventsRequest] =
useState(null);
- const { getTransformChangesIfTheyExist } = useTransforms();
const [networkKpiNetworkEventsResponse, setNetworkKpiNetworkEventsResponse] =
useState({
@@ -131,29 +129,23 @@ export const useNetworkKpiNetworkEvents = ({
useEffect(() => {
setNetworkKpiNetworkEventsRequest((prevRequest) => {
- const { indices, factoryQueryType, timerange } = getTransformChangesIfTheyExist({
+ const myRequest = {
+ ...(prevRequest ?? {}),
+ defaultIndex: indexNames,
factoryQueryType: NetworkKpiQueries.networkEvents,
- indices: indexNames,
- filterQuery,
+ filterQuery: createFilter(filterQuery),
timerange: {
interval: '12h',
from: startDate,
to: endDate,
},
- });
- const myRequest = {
- ...(prevRequest ?? {}),
- defaultIndex: indices,
- factoryQueryType,
- filterQuery: createFilter(filterQuery),
- timerange,
};
if (!deepEqual(prevRequest, myRequest)) {
return myRequest;
}
return prevRequest;
});
- }, [indexNames, endDate, filterQuery, startDate, getTransformChangesIfTheyExist]);
+ }, [indexNames, endDate, filterQuery, startDate]);
useEffect(() => {
networkKpiNetworkEventsSearch(networkKpiNetworkEventsRequest);
diff --git a/x-pack/plugins/security_solution/public/network/containers/kpi_network/tls_handshakes/index.tsx b/x-pack/plugins/security_solution/public/network/containers/kpi_network/tls_handshakes/index.tsx
index ba42d79ad0eed..b5e1eaa401a46 100644
--- a/x-pack/plugins/security_solution/public/network/containers/kpi_network/tls_handshakes/index.tsx
+++ b/x-pack/plugins/security_solution/public/network/containers/kpi_network/tls_handshakes/index.tsx
@@ -10,7 +10,6 @@ import { noop } from 'lodash/fp';
import { useCallback, useEffect, useRef, useState } from 'react';
import { Subscription } from 'rxjs';
-import { useTransforms } from '../../../../transforms/containers/use_transforms';
import { useAppToasts } from '../../../../common/hooks/use_app_toasts';
import { inputsModel } from '../../../../common/store';
import { createFilter } from '../../../../common/containers/helpers';
@@ -62,7 +61,6 @@ export const useNetworkKpiTlsHandshakes = ({
const [loading, setLoading] = useState(false);
const [networkKpiTlsHandshakesRequest, setNetworkKpiTlsHandshakesRequest] =
useState(null);
- const { getTransformChangesIfTheyExist } = useTransforms();
const [networkKpiTlsHandshakesResponse, setNetworkKpiTlsHandshakesResponse] =
useState({
@@ -130,30 +128,23 @@ export const useNetworkKpiTlsHandshakes = ({
useEffect(() => {
setNetworkKpiTlsHandshakesRequest((prevRequest) => {
- const { indices, factoryQueryType, timerange } = getTransformChangesIfTheyExist({
+ const myRequest = {
+ ...(prevRequest ?? {}),
+ defaultIndex: indexNames,
factoryQueryType: NetworkKpiQueries.tlsHandshakes,
- indices: indexNames,
- filterQuery,
+ filterQuery: createFilter(filterQuery),
timerange: {
interval: '12h',
from: startDate,
to: endDate,
},
- });
-
- const myRequest = {
- ...(prevRequest ?? {}),
- defaultIndex: indices,
- factoryQueryType,
- filterQuery: createFilter(filterQuery),
- timerange,
};
if (!deepEqual(prevRequest, myRequest)) {
return myRequest;
}
return prevRequest;
});
- }, [indexNames, endDate, filterQuery, startDate, getTransformChangesIfTheyExist]);
+ }, [indexNames, endDate, filterQuery, startDate]);
useEffect(() => {
networkKpiTlsHandshakesSearch(networkKpiTlsHandshakesRequest);
diff --git a/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_private_ips/index.tsx b/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_private_ips/index.tsx
index b68c4fcb698c0..fafd38cf15f73 100644
--- a/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_private_ips/index.tsx
+++ b/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_private_ips/index.tsx
@@ -10,7 +10,6 @@ import { noop } from 'lodash/fp';
import { useCallback, useEffect, useRef, useState } from 'react';
import { Subscription } from 'rxjs';
-import { useTransforms } from '../../../../transforms/containers/use_transforms';
import { useAppToasts } from '../../../../common/hooks/use_app_toasts';
import { inputsModel } from '../../../../common/store';
import { createFilter } from '../../../../common/containers/helpers';
@@ -66,7 +65,6 @@ export const useNetworkKpiUniquePrivateIps = ({
const [loading, setLoading] = useState(false);
const [networkKpiUniquePrivateIpsRequest, setNetworkKpiUniquePrivateIpsRequest] =
useState(null);
- const { getTransformChangesIfTheyExist } = useTransforms();
const [networkKpiUniquePrivateIpsResponse, setNetworkKpiUniquePrivateIpsResponse] =
useState({
@@ -142,30 +140,23 @@ export const useNetworkKpiUniquePrivateIps = ({
useEffect(() => {
setNetworkKpiUniquePrivateIpsRequest((prevRequest) => {
- const { indices, factoryQueryType, timerange } = getTransformChangesIfTheyExist({
+ const myRequest = {
+ ...(prevRequest ?? {}),
+ defaultIndex: indexNames,
factoryQueryType: NetworkKpiQueries.uniquePrivateIps,
- indices: indexNames,
- filterQuery,
+ filterQuery: createFilter(filterQuery),
timerange: {
interval: '12h',
from: startDate,
to: endDate,
},
- });
-
- const myRequest = {
- ...(prevRequest ?? {}),
- defaultIndex: indices,
- factoryQueryType,
- filterQuery: createFilter(filterQuery),
- timerange,
};
if (!deepEqual(prevRequest, myRequest)) {
return myRequest;
}
return prevRequest;
});
- }, [indexNames, endDate, filterQuery, startDate, getTransformChangesIfTheyExist]);
+ }, [indexNames, endDate, filterQuery, startDate]);
useEffect(() => {
networkKpiUniquePrivateIpsSearch(networkKpiUniquePrivateIpsRequest);
diff --git a/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx b/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx
index 6110e84804fe3..4bb8f62b10a87 100644
--- a/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx
+++ b/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx
@@ -29,7 +29,6 @@ import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/pl
import { getInspectResponse } from '../../../helpers';
import { InspectResponse } from '../../../types';
import * as i18n from './translations';
-import { useTransforms } from '../../../transforms/containers/use_transforms';
import { useAppToasts } from '../../../common/hooks/use_app_toasts';
export const ID = 'networkTopCountriesQuery';
@@ -76,7 +75,6 @@ export const useNetworkTopCountries = ({
const searchSubscription$ = useRef(new Subscription());
const [loading, setLoading] = useState(false);
const queryId = useMemo(() => `${ID}-${flowTarget}`, [flowTarget]);
- const { getTransformChangesIfTheyExist } = useTransforms();
const [networkTopCountriesRequest, setHostRequest] =
useState(null);
@@ -170,45 +168,27 @@ export const useNetworkTopCountries = ({
useEffect(() => {
setHostRequest((prevRequest) => {
- const { indices, factoryQueryType, timerange } = getTransformChangesIfTheyExist({
- factoryQueryType: NetworkQueries.topCountries,
- indices: indexNames,
- filterQuery,
- timerange: {
- interval: '12h',
- from: startDate,
- to: endDate,
- },
- });
-
const myRequest = {
...(prevRequest ?? {}),
- defaultIndex: indices,
- factoryQueryType,
+ defaultIndex: indexNames,
+ factoryQueryType: NetworkQueries.topCountries,
filterQuery: createFilter(filterQuery),
flowTarget,
ip,
pagination: generateTablePaginationOptions(activePage, limit),
sort,
- timerange,
+ timerange: {
+ interval: '12h',
+ from: startDate,
+ to: endDate,
+ },
};
if (!deepEqual(prevRequest, myRequest)) {
return myRequest;
}
return prevRequest;
});
- }, [
- activePage,
- indexNames,
- endDate,
- filterQuery,
- ip,
- limit,
- startDate,
- sort,
- flowTarget,
- getTransformChangesIfTheyExist,
- ]);
+ }, [activePage, indexNames, endDate, filterQuery, ip, limit, startDate, sort, flowTarget]);
useEffect(() => {
networkTopCountriesSearch(networkTopCountriesRequest);
diff --git a/x-pack/plugins/security_solution/public/network/containers/network_top_n_flow/index.tsx b/x-pack/plugins/security_solution/public/network/containers/network_top_n_flow/index.tsx
index 022b76c315c17..26d2f7a9d1df5 100644
--- a/x-pack/plugins/security_solution/public/network/containers/network_top_n_flow/index.tsx
+++ b/x-pack/plugins/security_solution/public/network/containers/network_top_n_flow/index.tsx
@@ -29,7 +29,6 @@ import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/pl
import { getInspectResponse } from '../../../helpers';
import { InspectResponse } from '../../../types';
import * as i18n from './translations';
-import { useTransforms } from '../../../transforms/containers/use_transforms';
import { useAppToasts } from '../../../common/hooks/use_app_toasts';
export const ID = 'networkTopNFlowQuery';
@@ -75,7 +74,6 @@ export const useNetworkTopNFlow = ({
const abortCtrl = useRef(new AbortController());
const searchSubscription$ = useRef(new Subscription());
const [loading, setLoading] = useState(false);
- const { getTransformChangesIfTheyExist } = useTransforms();
const [networkTopNFlowRequest, setTopNFlowRequest] =
useState(null);
@@ -168,25 +166,19 @@ export const useNetworkTopNFlow = ({
useEffect(() => {
setTopNFlowRequest((prevRequest) => {
- const { indices, factoryQueryType, timerange } = getTransformChangesIfTheyExist({
- factoryQueryType: NetworkQueries.topNFlow,
- indices: indexNames,
- filterQuery,
- timerange: {
- interval: '12h',
- from: startDate,
- to: endDate,
- },
- });
const myRequest = {
...(prevRequest ?? {}),
- defaultIndex: indices,
- factoryQueryType,
+ defaultIndex: indexNames,
+ factoryQueryType: NetworkQueries.topNFlow,
filterQuery: createFilter(filterQuery),
flowTarget,
ip,
pagination: generateTablePaginationOptions(activePage, limit),
- timerange,
+ timerange: {
+ interval: '12h',
+ from: startDate,
+ to: endDate,
+ },
sort,
};
if (!deepEqual(prevRequest, myRequest)) {
@@ -194,18 +186,7 @@ export const useNetworkTopNFlow = ({
}
return prevRequest;
});
- }, [
- activePage,
- endDate,
- filterQuery,
- indexNames,
- ip,
- limit,
- startDate,
- sort,
- flowTarget,
- getTransformChangesIfTheyExist,
- ]);
+ }, [activePage, endDate, filterQuery, indexNames, ip, limit, startDate, sort, flowTarget]);
useEffect(() => {
networkTopNFlowSearch(networkTopNFlowRequest);
diff --git a/x-pack/plugins/security_solution/public/risk_score/containers/all/index.tsx b/x-pack/plugins/security_solution/public/risk_score/containers/all/index.tsx
index 8c95a081b3e86..fe91c2fc1af9e 100644
--- a/x-pack/plugins/security_solution/public/risk_score/containers/all/index.tsx
+++ b/x-pack/plugins/security_solution/public/risk_score/containers/all/index.tsx
@@ -28,7 +28,6 @@ import * as i18n from './translations';
import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/plugins/data/common';
import { getInspectResponse } from '../../../helpers';
import { InspectResponse } from '../../../types';
-import { useTransforms } from '../../../transforms/containers/use_transforms';
import { useAppToasts } from '../../../common/hooks/use_app_toasts';
import { isIndexNotFoundError } from '../../../common/utils/exceptions';
import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features';
@@ -135,7 +134,6 @@ export const useRiskScore = (featureEnabled);
const [riskScoreRequest, setRiskScoreRequest] = useState(null);
- const { getTransformChangesIfTheyExist } = useTransforms();
const { addError, addWarning } = useAppToasts();
const [riskScoreResponse, setRiskScoreResponse] = useState>({
@@ -247,16 +245,7 @@ export const useRiskScore = {
riskScoreSearch(riskScoreRequest);
diff --git a/x-pack/plugins/security_solution/public/transforms/containers/api.ts b/x-pack/plugins/security_solution/public/transforms/containers/api.ts
deleted file mode 100644
index 0a796286de1aa..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/containers/api.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { KibanaServices } from '../../common/lib/kibana';
-
-export interface CreateTransforms {
- signal: AbortSignal;
- // TODO: Stronger types from the metrics_entities project
- bodies: unknown[];
-}
-
-export interface CreateTransform {
- signal: AbortSignal;
- // TODO: Stronger types from the metrics_entities project
- body: unknown;
-}
-
-/**
- * Creates transforms given a configuration
- * @param signal AbortSignal for cancelling request
- * @param bodies The bodies for the REST interface that is going to create them one at a time.
- *
- * TODO: Once there is a _bulk API, then we can do these all at once
- * @throws An error if response is not OK
- */
-export const createTransforms = async ({ bodies, signal }: CreateTransforms): Promise => {
- for (const body of bodies) {
- await createTransform({ body, signal });
- }
-};
-
-/**
- * Creates a single transform given a configuration
- * @param signal AbortSignal for cancelling request
- * @param bodies The body for the REST interface that is going to it.
- * @throws An error if response is not OK
- */
-export const createTransform = async ({ body, signal }: CreateTransform): Promise => {
- // TODO: Use constants for the url here or from the metrics package.
- return KibanaServices.get().http.fetch('/api/metrics_entities/transforms', {
- method: 'POST',
- body: JSON.stringify(body),
- signal,
- });
-};
diff --git a/x-pack/plugins/security_solution/public/transforms/containers/translations.ts b/x-pack/plugins/security_solution/public/transforms/containers/translations.ts
deleted file mode 100644
index 2fdd285dddd85..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/containers/translations.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { i18n } from '@kbn/i18n';
-
-export const TRANSFORM_CREATE_FAILURE = i18n.translate(
- 'xpack.securitySolution.containers.transforms.errorCreatingTransformsLabel',
- {
- defaultMessage: 'Failed to create transforms',
- }
-);
diff --git a/x-pack/plugins/security_solution/public/transforms/containers/use_create_transforms.ts b/x-pack/plugins/security_solution/public/transforms/containers/use_create_transforms.ts
deleted file mode 100644
index 789a35939cba8..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/containers/use_create_transforms.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-import { useEffect, useState } from 'react';
-import { defaultTransformsSetting, DEFAULT_TRANSFORMS } from '../../../common/constants';
-import { TransformConfigSchema } from '../../../common/transforms/types';
-import { errorToToaster, useStateToaster } from '../../common/components/toasters';
-import * as i18n from './translations';
-import { createTransforms } from './api';
-import { useUiSetting$ } from '../../common/lib/kibana';
-import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features';
-
-type Func = () => Promise;
-
-export interface ReturnTransform {
- loading: boolean;
- createTransforms: Func;
-}
-
-export const noop: Func = () => Promise.resolve();
-
-export const useCreateTransforms = (): ReturnTransform => {
- const [loading, setLoading] = useState(true);
- const [, dispatchToaster] = useStateToaster();
- const [transformSettings] = useUiSetting$(
- DEFAULT_TRANSFORMS,
- JSON.stringify(defaultTransformsSetting) as unknown as TransformConfigSchema // TODO: The types are not 100% correct within uiSettings$, so I have to cast here. Once that is fixed, this cast can be removed
- );
- const [transforms, setTransforms] = useState>({
- createTransforms: noop,
- });
- // TODO: Once we are past experimental phase this code should be removed
- const metricsEntitiesEnabled = useIsExperimentalFeatureEnabled('metricsEntitiesEnabled');
-
- useEffect(() => {
- let isSubscribed = true;
- const abortCtrl = new AbortController();
-
- const createTheTransforms = async () => {
- // TODO: Once we are past experimental phase this code should be removed
- if (!metricsEntitiesEnabled) {
- return;
- }
-
- // double check one more time and not create the transform if the settings are not enabled.
- if (!transformSettings.enabled || !transformSettings.auto_create) {
- return;
- }
- let isFetchingData = false;
- setLoading(true);
- const bodies = getTransformBodies(transformSettings);
- try {
- await createTransforms({ bodies, signal: abortCtrl.signal });
- if (isSubscribed) {
- isFetchingData = true;
- }
- } catch (error) {
- if (isSubscribed) {
- if (error.body.statusCode !== 404 && error.body.status_code !== 404) {
- errorToToaster({ title: i18n.TRANSFORM_CREATE_FAILURE, error, dispatchToaster });
- } else {
- // This means that the plugin is disabled and/or the user does not have permissions
- // so we do not show an error toaster for this condition since this is a 404 error message
- }
- }
- }
- if (isSubscribed && !isFetchingData) {
- setLoading(false);
- }
- };
-
- if (transformSettings.enabled) {
- setTransforms({ createTransforms: createTheTransforms });
- } else {
- setTransforms({ createTransforms: noop });
- }
- return () => {
- isSubscribed = false;
- abortCtrl.abort();
- };
- }, [dispatchToaster, transformSettings, metricsEntitiesEnabled]);
-
- return { loading, ...transforms };
-};
-
-export const getTransformBodies = (transformSettings: TransformConfigSchema) => {
- // eslint-disable-next-line @typescript-eslint/naming-convention
- const { query, auto_start, max_page_search_size, docs_per_second } = transformSettings;
- return transformSettings.settings.map(({ prefix, indices }) => {
- return {
- query,
- prefix,
- modules: [
- 'host_metrics',
- 'host_entities',
- 'network_entities',
- 'network_metrics',
- 'user_entities',
- 'user_metrics',
- ],
- indices,
- auto_start,
- settings: {
- max_page_search_size,
- docs_per_second,
- },
- };
- });
-};
diff --git a/x-pack/plugins/security_solution/public/transforms/containers/use_transforms.ts b/x-pack/plugins/security_solution/public/transforms/containers/use_transforms.ts
deleted file mode 100644
index 9a98fb0815a3e..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/containers/use_transforms.ts
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-import { useMemo, useState } from 'react';
-import { ESQuery } from '../../../common/typed_json';
-import {
- FactoryQueryTypes,
- MatrixHistogramType,
- TimerangeInput,
-} from '../../../common/search_strategy';
-import { TransformConfigSchema } from '../../../common/transforms/types';
-import { defaultTransformsSetting, DEFAULT_TRANSFORMS } from '../../../common/constants';
-import { useUiSetting$ } from '../../common/lib/kibana';
-import { getTransformChangesIfTheyExist } from '../utils';
-import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features';
-
-export type TransformChangesIfTheyExist = ({
- factoryQueryType,
- indices,
- filterQuery,
- histogramType,
- timerange,
-}: {
- factoryQueryType: FactoryQueryTypes;
- indices: string[];
- filterQuery: ESQuery | string | undefined;
- histogramType?: MatrixHistogramType;
- timerange: TimerangeInput;
-}) => {
- indices: string[];
- factoryQueryType: FactoryQueryTypes;
- histogramType?: MatrixHistogramType;
- timerange: TimerangeInput;
-};
-
-export interface ReturnTransform {
- getTransformChangesIfTheyExist: TransformChangesIfTheyExist;
-}
-
-export const useTransforms = (): ReturnTransform => {
- const [transformSettings] = useUiSetting$(
- DEFAULT_TRANSFORMS,
- JSON.stringify(defaultTransformsSetting) as unknown as TransformConfigSchema // TODO: The types are not 100% correct within uiSettings$, so I have to cast here. Once that is fixed, this cast can be removed
- );
- // TODO: Once we are past experimental phase this code should be removed
- const metricsEntitiesEnabled = useIsExperimentalFeatureEnabled('metricsEntitiesEnabled');
- const [transforms, setTransforms] = useState({
- getTransformChangesIfTheyExist: ({
- factoryQueryType,
- indices,
- filterQuery,
- histogramType,
- timerange,
- }) => {
- if (metricsEntitiesEnabled) {
- return getTransformChangesIfTheyExist({
- factoryQueryType,
- indices,
- filterQuery,
- transformSettings,
- histogramType,
- timerange,
- });
- } else {
- // TODO: Once the experimental flag is removed, then remove this return statement
- return {
- indices,
- filterQuery,
- timerange,
- factoryQueryType,
- };
- }
- },
- });
-
- useMemo(() => {
- setTransforms({
- getTransformChangesIfTheyExist: ({
- factoryQueryType,
- indices,
- filterQuery,
- histogramType,
- timerange,
- }) => {
- if (metricsEntitiesEnabled) {
- return getTransformChangesIfTheyExist({
- factoryQueryType,
- indices,
- transformSettings,
- filterQuery,
- histogramType,
- timerange,
- });
- } else {
- // TODO: Once the experimental flag is removed, then remove this return statement
- return {
- indices,
- filterQuery,
- timerange,
- factoryQueryType,
- };
- }
- },
- });
- }, [transformSettings, metricsEntitiesEnabled]);
-
- return { ...transforms };
-};
diff --git a/x-pack/plugins/security_solution/public/transforms/jest.config.js b/x-pack/plugins/security_solution/public/transforms/jest.config.js
deleted file mode 100644
index 095a70933abc1..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/jest.config.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-module.exports = {
- preset: '@kbn/test',
- rootDir: '../../../../..',
- roots: ['/x-pack/plugins/security_solution/public/transforms'],
- coverageDirectory:
- '/target/kibana-coverage/jest/x-pack/plugins/security_solution/public/transforms',
- coverageReporters: ['text', 'html'],
- collectCoverageFrom: [
- '/x-pack/plugins/security_solution/public/transforms/**/*.{ts,tsx}',
- ],
- // See: https://github.com/elastic/kibana/issues/117255, the moduleNameMapper creates mocks to avoid memory leaks from kibana core.
- moduleNameMapper: {
- 'core/server$': '/x-pack/plugins/security_solution/server/__mocks__/core.mock.ts',
- 'task_manager/server$':
- '/x-pack/plugins/security_solution/server/__mocks__/task_manager.mock.ts',
- 'alerting/server$': '/x-pack/plugins/security_solution/server/__mocks__/alert.mock.ts',
- 'actions/server$': '/x-pack/plugins/security_solution/server/__mocks__/action.mock.ts',
- },
-};
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/adjust_timerange.test.ts b/x-pack/plugins/security_solution/public/transforms/utils/adjust_timerange.test.ts
deleted file mode 100644
index daf3ab5365bef..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/adjust_timerange.test.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { adjustTimeRange } from './adjust_timerange';
-import moment from 'moment';
-
-/** Get the return type of adjustTimeRange for TypeScript checks against expected */
-type ReturnTypeAdjustTimeRange = ReturnType;
-
-describe('adjust_timerange', () => {
- beforeEach(() => {
- // Adds extra switch to suppress deprecation warnings that moment does not expose in TypeScript
- (
- moment as typeof moment & {
- suppressDeprecationWarnings: boolean;
- }
- ).suppressDeprecationWarnings = true;
- });
-
- afterEach(() => {
- // Adds extra switch to suppress deprecation warnings that moment does not expose in TypeScript
- (
- moment as typeof moment & {
- suppressDeprecationWarnings: boolean;
- }
- ).suppressDeprecationWarnings = false;
- });
-
- test('it will adjust the time range from by rounding down by an hour within "from"', () => {
- expect(
- adjustTimeRange({
- interval: '5m',
- to: '2021-07-06T22:07:56.972Z',
- from: '2021-07-06T22:07:56.972Z',
- })
- ).toMatchObject>({
- timeRangeAdjusted: {
- interval: '5m',
- to: '2021-07-06T22:07:56.972Z',
- from: '2021-07-06T22:00:00.000Z', // <-- Rounded down by an hour
- },
- });
- });
-
- test('it will compute the duration between to and and from', () => {
- expect(
- adjustTimeRange({
- interval: '5m',
- to: '2021-07-06T22:08:56.972Z',
- from: '2021-07-06T22:07:56.972Z',
- }).duration?.asMinutes()
- ).toEqual(1);
- });
-
- test('it will return "undefined" if the to and from are invalid dateMath parsable', () => {
- expect(
- adjustTimeRange({
- interval: '5m',
- to: 'now-invalid',
- from: 'now-invalid2',
- })
- ).toMatchObject>({
- timeRangeAdjusted: undefined,
- duration: undefined,
- });
- });
-});
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/adjust_timerange.ts b/x-pack/plugins/security_solution/public/transforms/utils/adjust_timerange.ts
deleted file mode 100644
index 464ccd8692512..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/adjust_timerange.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import dateMath from '@kbn/datemath';
-import moment, { Duration } from 'moment';
-import type { TimerangeInput } from '../../../common/search_strategy';
-
-export interface TimeRangeAdjusted {
- timeRangeAdjusted: TimerangeInput | undefined;
- duration: Duration | undefined;
-}
-
-/**
- * Adjusts a given timerange by rounding the "from" down by an hour and returning
- * the duration between "to" and "from". The duration is typically analyzed to determine
- * if the adjustment should be made or not. Although we check "to" and use "to" for duration
- * we are careful to still return "to: timerange.to", which is the original input to be careful
- * about accidental bugs from trying to over parse or change relative date time ranges.
- * @param timerange The timeRange to determine if we adjust or not
- * @returns The time input adjustment and a duration
- */
-export const adjustTimeRange = (timerange: TimerangeInput): TimeRangeAdjusted => {
- const from = dateMath.parse(timerange.from);
- const to = dateMath.parse(timerange.to);
- if (from == null || to == null) {
- return { timeRangeAdjusted: undefined, duration: undefined };
- } else {
- const newTimerange: TimerangeInput = {
- from: moment(from).startOf('hour').toISOString(),
- to: timerange.to,
- interval: timerange.interval,
- };
- const duration = moment.duration(to.diff(from));
- return { timeRangeAdjusted: newTimerange, duration };
- }
-};
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/create_indices_from_prefix.test.ts b/x-pack/plugins/security_solution/public/transforms/utils/create_indices_from_prefix.test.ts
deleted file mode 100644
index 2cdb1c4ebc2cd..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/create_indices_from_prefix.test.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { createIndicesFromPrefix } from './create_indices_from_prefix';
-
-/** Get the return type of createIndicesFromPrefix for TypeScript checks against expected */
-type ReturnTypeCreateIndicesFromPrefix = ReturnType;
-
-describe('create_indices_from_prefix', () => {
- test('returns empty array given an empty array', () => {
- expect(
- createIndicesFromPrefix({
- transformIndices: [],
- prefix: 'prefix',
- })
- ).toEqual([]);
- });
-
- test('returns expected prefix given a set of indices', () => {
- expect(
- createIndicesFromPrefix({
- transformIndices: ['index_1', 'index_2'],
- prefix: 'prefix',
- })
- ).toEqual(['.estc_prefix_index_1', '.estc_prefix_index_2']);
- });
-});
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/create_indices_from_prefix.ts b/x-pack/plugins/security_solution/public/transforms/utils/create_indices_from_prefix.ts
deleted file mode 100644
index de63933ba4475..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/create_indices_from_prefix.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ELASTIC_NAME } from '../../../common/constants';
-
-/**
- * Given a set of input indices and a prefix this will return the elastic name
- * concatenated with the prefix.
- * @param transformIndices The indices to add the prefix to
- * @param prefix The prefix to add along with the elastic name
- * @returns The indices with the prefix string
- */
-export const createIndicesFromPrefix = ({
- transformIndices,
- prefix,
-}: {
- transformIndices: string[];
- prefix: string;
-}): string[] => {
- return transformIndices.map((index) => `.${ELASTIC_NAME}_${prefix}_${index}`);
-};
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_settings_match.test.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_settings_match.test.ts
deleted file mode 100644
index a58757c261624..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_settings_match.test.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { getSettingsMatch } from './get_settings_match';
-import { getTransformConfigSchemaMock } from './transform_config_schema.mock';
-
-/** Get the return type of createIndicesFromPrefix for TypeScript checks against expected */
-type ReturnTypeCreateIndicesFromPrefix = ReturnType;
-
-describe('get_settings_match', () => {
- test('it returns undefined given an empty array of indices', () => {
- expect(
- getSettingsMatch({
- indices: [],
- transformSettings: getTransformConfigSchemaMock(),
- })
- ).toEqual(undefined);
- });
-
- test('it returns a setting given an index pattern that matches', () => {
- expect(
- getSettingsMatch({
- indices: [
- 'auditbeat-*',
- 'endgame-*',
- 'filebeat-*',
- 'logs-*',
- 'packetbeat-*',
- 'winlogbeat-*',
- ],
- transformSettings: getTransformConfigSchemaMock(),
- })
- ).toEqual(getTransformConfigSchemaMock().settings[0]);
- });
-
- test('it returns a setting given an index pattern that matches even if the indices are different order', () => {
- expect(
- getSettingsMatch({
- indices: [
- 'endgame-*',
- 'filebeat-*',
- 'logs-*',
- 'auditbeat-*',
- 'packetbeat-*',
- 'winlogbeat-*',
- ],
- transformSettings: getTransformConfigSchemaMock(),
- })
- ).toEqual(getTransformConfigSchemaMock().settings[0]);
- });
-
- test('it returns a setting given an index pattern that matches and removes any that have a dash in them meaning to subtract them', () => {
- expect(
- getSettingsMatch({
- indices: [
- 'endgame-*',
- 'filebeat-*',
- 'logs-*',
- 'auditbeat-*',
- 'packetbeat-*',
- 'winlogbeat-*',
- '-subtract-1', // extra dashed one that should still allow a match
- '-subtract-2', // extra dashed one that should still allow a match
- ],
- transformSettings: getTransformConfigSchemaMock(),
- })
- ).toEqual(getTransformConfigSchemaMock().settings[0]);
- });
-
- test('it returns "undefined" given a set of indices that do not match a setting', () => {
- expect(
- getSettingsMatch({
- indices: ['endgame-*', 'filebeat-*', 'logs-*', 'auditbeat-*', 'packetbeat-*'],
- transformSettings: getTransformConfigSchemaMock(),
- })
- ).toEqual(undefined);
- });
-});
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_settings_match.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_settings_match.ts
deleted file mode 100644
index ed7be4a530dcf..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_settings_match.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { TransformConfigSchema } from '../../../common/transforms/types';
-
-/**
- * Given a transform setting and indices this will return either the particular setting
- * that matches the index or it will return undefined if it is not found
- * @param indices The indices to check against the transform
- * @returns Either the setting if it matches or an undefined if it cannot find one
- */
-export const getSettingsMatch = ({
- indices,
- transformSettings,
-}: {
- indices: string[];
- transformSettings: TransformConfigSchema;
-}): TransformConfigSchema['settings'][0] | undefined => {
- const removeAllSubtractedIndices = indices.filter((index) => !index.startsWith('-')).sort();
- return transformSettings.settings.find((setting) => {
- const match = setting.data_sources.some((dataSource) => {
- return dataSource.sort().join() === removeAllSubtractedIndices.join();
- });
- if (match) {
- return setting;
- } else {
- return undefined;
- }
- });
-};
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes.test.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes.test.ts
deleted file mode 100644
index 702d259f98615..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes.test.ts
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { getTransformChanges } from './get_transform_changes';
-import { getTransformConfigSchemaMock } from './transform_config_schema.mock';
-import {
- HostsKpiQueries,
- HostsQueries,
- MatrixHistogramQuery,
- MatrixHistogramQueryEntities,
- MatrixHistogramType,
- NetworkKpiQueries,
- NetworkQueries,
- UsersQueries,
-} from '../../../common/search_strategy';
-
-/** Get the return type of createIndicesFromPrefix for TypeScript checks against expected */
-type ReturnTypeGetTransformChanges = ReturnType;
-
-describe('get_transform_changes', () => {
- describe('kpi transforms', () => {
- test('it gets a transform change for kpiHosts', () => {
- expect(
- getTransformChanges({
- factoryQueryType: HostsKpiQueries.kpiHosts,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: HostsKpiQueries.kpiHostsEntities,
- indices: ['.estc_all_host_ent*'],
- });
- });
-
- test('it gets a transform change for kpiAuthentications', () => {
- expect(
- getTransformChanges({
- factoryQueryType: HostsKpiQueries.kpiAuthentications,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: HostsKpiQueries.kpiAuthenticationsEntities,
- indices: ['.estc_all_user_ent*'],
- });
- });
-
- test('it gets a transform change for kpiUniqueIps', () => {
- expect(
- getTransformChanges({
- factoryQueryType: HostsKpiQueries.kpiUniqueIps,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: HostsKpiQueries.kpiUniqueIpsEntities,
- indices: ['.estc_all_src_ip_ent*', '.estc_all_dest_ip_ent*'],
- });
- });
- });
-
- describe('host transforms', () => {
- test('it gets a transform change for hosts', () => {
- expect(
- getTransformChanges({
- factoryQueryType: HostsQueries.hosts,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: HostsQueries.hostsEntities,
- indices: ['.estc_all_host_ent*'],
- });
- });
-
- test('it gets a transform change for authentications', () => {
- expect(
- getTransformChanges({
- factoryQueryType: UsersQueries.authentications,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: UsersQueries.authenticationsEntities,
- indices: ['.estc_all_user_ent*'],
- });
- });
- });
-
- describe('network transforms', () => {
- test('it gets a transform change for topCountries', () => {
- expect(
- getTransformChanges({
- factoryQueryType: NetworkQueries.topCountries,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: NetworkQueries.topCountriesEntities,
- indices: ['.estc_all_src_iso_ent*', '.estc_all_dest_iso_ent*'],
- });
- });
-
- test('it gets a transform change for topNFlow', () => {
- expect(
- getTransformChanges({
- factoryQueryType: NetworkQueries.topNFlow,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: NetworkQueries.topNFlowEntities,
- indices: ['.estc_all_src_ip_ent*', '.estc_all_dest_ip_ent*'],
- });
- });
-
- test('it gets a transform change for dns', () => {
- expect(
- getTransformChanges({
- factoryQueryType: NetworkKpiQueries.dns,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: NetworkKpiQueries.dnsEntities,
- indices: ['.estc_all_ip_met*'],
- });
- });
-
- test('it gets a transform change for networkEvents', () => {
- expect(
- getTransformChanges({
- factoryQueryType: NetworkKpiQueries.networkEvents,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: NetworkKpiQueries.networkEventsEntities,
- indices: ['.estc_all_ip_met*'],
- });
- });
-
- test('it gets a transform change for tlsHandshakes', () => {
- expect(
- getTransformChanges({
- factoryQueryType: NetworkKpiQueries.tlsHandshakes,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: NetworkKpiQueries.tlsHandshakesEntities,
- indices: ['.estc_all_ip_met*'],
- });
- });
- });
-
- describe('matrix transforms', () => {
- test('it gets a transform change for authentications', () => {
- expect(
- getTransformChanges({
- factoryQueryType: MatrixHistogramQuery,
- histogramType: MatrixHistogramType.authentications,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- histogramType: MatrixHistogramType.authenticationsEntities,
- factoryQueryType: MatrixHistogramQueryEntities,
- indices: ['.estc_all_user_met*'],
- });
- });
- });
-
- describe('unsupported/undefined transforms', () => {
- test('it returned unsupported/undefined for firstOrLastSeen since there are not transforms for it', () => {
- expect(
- getTransformChanges({
- factoryQueryType: HostsQueries.firstOrLastSeen,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual(undefined);
- });
- });
-});
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes.ts
deleted file mode 100644
index 1a72c556490a5..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { getTransformChangesForHosts } from './get_transform_changes_for_hosts';
-import { getTransformChangesForKpi } from './get_transform_changes_for_kpi';
-import { getTransformChangesForMatrixHistogram } from './get_transform_changes_for_matrix_histogram';
-import { getTransformChangesForNetwork } from './get_transform_changes_for_network';
-import { getTransformChangesForUsers } from './get_transform_changes_for_users';
-import { GetTransformChanges } from './types';
-
-export const getTransformChanges: GetTransformChanges = ({
- factoryQueryType,
- settings,
- histogramType,
-}) => {
- const kpiTransform = getTransformChangesForKpi({ factoryQueryType, settings });
- if (kpiTransform != null) {
- return kpiTransform;
- }
-
- const hostTransform = getTransformChangesForHosts({ factoryQueryType, settings });
- if (hostTransform != null) {
- return hostTransform;
- }
-
- const userTransform = getTransformChangesForUsers({ factoryQueryType, settings });
- if (userTransform != null) {
- return userTransform;
- }
-
- const networkTransform = getTransformChangesForNetwork({
- factoryQueryType,
- settings,
- });
- if (networkTransform != null) {
- return networkTransform;
- }
-
- const matrixHistogram = getTransformChangesForMatrixHistogram({
- factoryQueryType,
- settings,
- histogramType,
- });
- if (matrixHistogram != null) {
- return matrixHistogram;
- }
-
- // nothing matches
- return undefined;
-};
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_hosts.test.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_hosts.test.ts
deleted file mode 100644
index 8223e3a9cd6e6..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_hosts.test.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { getTransformChangesForHosts } from './get_transform_changes_for_hosts';
-import { HostsQueries } from '../../../common/search_strategy/security_solution/hosts';
-import { getTransformConfigSchemaMock } from './transform_config_schema.mock';
-
-/** Get the return type of getTransformChangesForHosts for TypeScript checks against expected */
-type ReturnTypeGetTransformChangesForHosts = ReturnType;
-
-describe('get_transform_changes_for_host', () => {
- test('it gets a transform change for hosts', () => {
- expect(
- getTransformChangesForHosts({
- factoryQueryType: HostsQueries.hosts,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: HostsQueries.hostsEntities,
- indices: ['.estc_all_host_ent*'],
- });
- });
-
- test('it returns an "undefined" for another value', () => {
- expect(
- getTransformChangesForHosts({
- factoryQueryType: HostsQueries.firstOrLastSeen,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual(undefined);
- });
-});
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_hosts.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_hosts.ts
deleted file mode 100644
index 265b2857d5397..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_hosts.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { HostsQueries } from '../../../common/search_strategy';
-import { createIndicesFromPrefix } from './create_indices_from_prefix';
-import { GetTransformChanges } from './types';
-
-/**
- * Given a factory query type this will return the transform changes such as the transform indices if it matches
- * the correct type, otherwise it will return "undefined"
- * @param factoryQueryType The query type to check if we have a transform for it and are capable of rendering one or not
- * @param settings The settings configuration to get the prefix from
- * @returns The transform type if we have one, otherwise undefined
- */
-export const getTransformChangesForHosts: GetTransformChanges = ({
- factoryQueryType,
- settings,
-}) => {
- switch (factoryQueryType) {
- case HostsQueries.hosts: {
- return {
- indices: createIndicesFromPrefix({
- prefix: settings.prefix,
- transformIndices: ['host_ent*'],
- }),
- factoryQueryType: HostsQueries.hostsEntities,
- };
- }
- default: {
- return undefined;
- }
- }
-};
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_kpi.test.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_kpi.test.ts
deleted file mode 100644
index 561874930feae..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_kpi.test.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { getTransformChangesForKpi } from './get_transform_changes_for_kpi';
-import { HostsKpiQueries } from '../../../common/search_strategy';
-import { HostsQueries } from '../../../common/search_strategy/security_solution/hosts';
-import { getTransformConfigSchemaMock } from './transform_config_schema.mock';
-
-/** Get the return type of getTransformChangesForKpi for TypeScript checks against expected */
-type ReturnTypeGetTransformChangesForKpi = ReturnType;
-
-describe('get_transform_changes_for_kpi', () => {
- test('it gets a transform change for kpiHosts', () => {
- expect(
- getTransformChangesForKpi({
- factoryQueryType: HostsKpiQueries.kpiHosts,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: HostsKpiQueries.kpiHostsEntities,
- indices: ['.estc_all_host_ent*'],
- });
- });
-
- test('it gets a transform change for kpiAuthentications', () => {
- expect(
- getTransformChangesForKpi({
- factoryQueryType: HostsKpiQueries.kpiAuthentications,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: HostsKpiQueries.kpiAuthenticationsEntities,
- indices: ['.estc_all_user_ent*'],
- });
- });
-
- test('it gets a transform change for kpiUniqueIps', () => {
- expect(
- getTransformChangesForKpi({
- factoryQueryType: HostsKpiQueries.kpiUniqueIps,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: HostsKpiQueries.kpiUniqueIpsEntities,
- indices: ['.estc_all_src_ip_ent*', '.estc_all_dest_ip_ent*'],
- });
- });
-
- test('it returns an "undefined" for another value', () => {
- expect(
- getTransformChangesForKpi({
- factoryQueryType: HostsQueries.firstOrLastSeen,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual(undefined);
- });
-});
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_kpi.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_kpi.ts
deleted file mode 100644
index 800d3189e0c7a..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_kpi.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-import { HostsKpiQueries } from '../../../common/search_strategy';
-import { createIndicesFromPrefix } from './create_indices_from_prefix';
-import { GetTransformChanges } from './types';
-
-/**
- * Given a factory query type this will return the transform changes such as the transform indices if it matches
- * the correct type, otherwise it will return "undefined"
- * @param factoryQueryType The query type to check if we have a transform for it and are capable of rendering one or not
- * @param settings The settings configuration to get the prefix from
- * @returns The transform type if we have one, otherwise undefined
- */
-export const getTransformChangesForKpi: GetTransformChanges = ({ factoryQueryType, settings }) => {
- switch (factoryQueryType) {
- case HostsKpiQueries.kpiHosts: {
- return {
- indices: createIndicesFromPrefix({
- prefix: settings.prefix,
- transformIndices: ['host_ent*'],
- }),
- factoryQueryType: HostsKpiQueries.kpiHostsEntities,
- };
- }
- case HostsKpiQueries.kpiAuthentications: {
- return {
- indices: createIndicesFromPrefix({
- prefix: settings.prefix,
- transformIndices: ['user_ent*'],
- }),
- factoryQueryType: HostsKpiQueries.kpiAuthenticationsEntities,
- };
- }
- case HostsKpiQueries.kpiUniqueIps: {
- return {
- indices: createIndicesFromPrefix({
- prefix: settings.prefix,
- transformIndices: ['src_ip_ent*', 'dest_ip_ent*'],
- }),
- factoryQueryType: HostsKpiQueries.kpiUniqueIpsEntities,
- };
- }
- default: {
- return undefined;
- }
- }
-};
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_matrix_histogram.test.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_matrix_histogram.test.ts
deleted file mode 100644
index 539fb960e4411..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_matrix_histogram.test.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import {
- MatrixHistogramType,
- MatrixHistogramQuery,
- MatrixHistogramQueryEntities,
-} from '../../../common/search_strategy';
-import { getTransformChangesForMatrixHistogram } from './get_transform_changes_for_matrix_histogram';
-import { HostsQueries } from '../../../common/search_strategy/security_solution/hosts';
-import { getTransformConfigSchemaMock } from './transform_config_schema.mock';
-
-/** Get the return type of getTransformChangesForMatrixHistogram for TypeScript checks against expected */
-type ReturnTypeGetTransformChangesForMatrixHistogram = ReturnType<
- typeof getTransformChangesForMatrixHistogram
->;
-
-describe('get_transform_changes_for_matrix_histogram', () => {
- test('it gets a transform change for authentications', () => {
- expect(
- getTransformChangesForMatrixHistogram({
- factoryQueryType: MatrixHistogramQuery,
- histogramType: MatrixHistogramType.authentications,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- histogramType: MatrixHistogramType.authenticationsEntities,
- factoryQueryType: MatrixHistogramQueryEntities,
- indices: ['.estc_all_user_met*'],
- });
- });
-
- test('it returns an "undefined" for another value', () => {
- expect(
- getTransformChangesForMatrixHistogram({
- factoryQueryType: HostsQueries.firstOrLastSeen,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual(undefined);
- });
-});
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_matrix_histogram.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_matrix_histogram.ts
deleted file mode 100644
index 36e8c2203200b..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_matrix_histogram.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import {
- MatrixHistogramQuery,
- MatrixHistogramQueryEntities,
- MatrixHistogramType,
-} from '../../../common/search_strategy';
-import { createIndicesFromPrefix } from './create_indices_from_prefix';
-import { GetTransformChanges } from './types';
-
-/**
- * Given a factory query type this will return the transform changes such as the transform indices if it matches
- * the correct type, otherwise it will return "undefined"
- * @param factoryQueryType The query type to check if we have a transform for it and are capable of rendering one or not
- * @param histogramType The histogram type to check if we have a transform for it and are capable fo rendering one or not
- * @param settings The settings configuration to get the prefix from
- * @returns The transform type if we have one, otherwise undefined
- */
-export const getTransformChangesForMatrixHistogram: GetTransformChanges = ({
- factoryQueryType,
- settings,
- histogramType,
-}) => {
- switch (factoryQueryType) {
- case MatrixHistogramQuery: {
- switch (histogramType) {
- case MatrixHistogramType.authentications: {
- return {
- indices: createIndicesFromPrefix({
- prefix: settings.prefix,
- transformIndices: ['user_met*'],
- }),
- factoryQueryType: MatrixHistogramQueryEntities,
- histogramType: MatrixHistogramType.authenticationsEntities,
- };
- }
- default: {
- return undefined;
- }
- }
- }
- default: {
- return undefined;
- }
- }
-};
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_network.test.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_network.test.ts
deleted file mode 100644
index ffac8853f6e67..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_network.test.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { getTransformChangesForNetwork } from './get_transform_changes_for_network';
-import { NetworkKpiQueries, NetworkQueries } from '../../../common/search_strategy';
-import { HostsQueries } from '../../../common/search_strategy/security_solution/hosts';
-import { getTransformConfigSchemaMock } from './transform_config_schema.mock';
-
-/** Get the return type of getTransformChangesForNetwork for TypeScript checks against expected */
-type ReturnTypeGetTransformChangesForNetwork = ReturnType;
-
-describe('get_transform_changes_for_network', () => {
- test('it gets a transform change for topCountries', () => {
- expect(
- getTransformChangesForNetwork({
- factoryQueryType: NetworkQueries.topCountries,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: NetworkQueries.topCountriesEntities,
- indices: ['.estc_all_src_iso_ent*', '.estc_all_dest_iso_ent*'],
- });
- });
-
- test('it gets a transform change for topNFlow', () => {
- expect(
- getTransformChangesForNetwork({
- factoryQueryType: NetworkQueries.topNFlow,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: NetworkQueries.topNFlowEntities,
- indices: ['.estc_all_src_ip_ent*', '.estc_all_dest_ip_ent*'],
- });
- });
-
- test('it gets a transform change for dns', () => {
- expect(
- getTransformChangesForNetwork({
- factoryQueryType: NetworkKpiQueries.dns,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: NetworkKpiQueries.dnsEntities,
- indices: ['.estc_all_ip_met*'],
- });
- });
-
- test('it gets a transform change for networkEvents', () => {
- expect(
- getTransformChangesForNetwork({
- factoryQueryType: NetworkKpiQueries.networkEvents,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: NetworkKpiQueries.networkEventsEntities,
- indices: ['.estc_all_ip_met*'],
- });
- });
-
- test('it gets a transform change for tlsHandshakes', () => {
- expect(
- getTransformChangesForNetwork({
- factoryQueryType: NetworkKpiQueries.tlsHandshakes,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: NetworkKpiQueries.tlsHandshakesEntities,
- indices: ['.estc_all_ip_met*'],
- });
- });
-
- test('it gets a transform change for uniquePrivateIps', () => {
- expect(
- getTransformChangesForNetwork({
- factoryQueryType: NetworkKpiQueries.uniquePrivateIps,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: NetworkKpiQueries.uniquePrivateIpsEntities,
- indices: ['.estc_all_src_ip_ent*', '.estc_all_dest_ip_ent*'],
- });
- });
-
- test('it returns an "undefined" for another value', () => {
- expect(
- getTransformChangesForNetwork({
- factoryQueryType: HostsQueries.firstOrLastSeen,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual(undefined);
- });
-});
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_network.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_network.ts
deleted file mode 100644
index a1ec0783235f8..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_network.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { NetworkKpiQueries, NetworkQueries } from '../../../common/search_strategy';
-import { createIndicesFromPrefix } from './create_indices_from_prefix';
-import { GetTransformChanges } from './types';
-
-/**
- * Given a factory query type this will return the transform changes such as the transform indices if it matches
- * the correct type, otherwise it will return "undefined"
- * @param factoryQueryType The query type to check if we have a transform for it and are capable of rendering one or not
- * @param settings The settings configuration to get the prefix from
- * @returns The transform type if we have one, otherwise undefined
- */
-export const getTransformChangesForNetwork: GetTransformChanges = ({
- factoryQueryType,
- settings,
-}) => {
- switch (factoryQueryType) {
- case NetworkQueries.topCountries: {
- return {
- indices: createIndicesFromPrefix({
- prefix: settings.prefix,
- transformIndices: ['src_iso_ent*', 'dest_iso_ent*'],
- }),
- factoryQueryType: NetworkQueries.topCountriesEntities,
- };
- }
- case NetworkQueries.topNFlow: {
- return {
- indices: createIndicesFromPrefix({
- prefix: settings.prefix,
- transformIndices: ['src_ip_ent*', 'dest_ip_ent*'],
- }),
- factoryQueryType: NetworkQueries.topNFlowEntities,
- };
- }
- case NetworkKpiQueries.dns: {
- return {
- indices: createIndicesFromPrefix({
- prefix: settings.prefix,
- transformIndices: ['ip_met*'],
- }),
- factoryQueryType: NetworkKpiQueries.dnsEntities,
- };
- }
- case NetworkKpiQueries.networkEvents: {
- return {
- indices: createIndicesFromPrefix({
- prefix: settings.prefix,
- transformIndices: ['ip_met*'],
- }),
- factoryQueryType: NetworkKpiQueries.networkEventsEntities,
- };
- }
- case NetworkKpiQueries.tlsHandshakes: {
- return {
- indices: createIndicesFromPrefix({
- prefix: settings.prefix,
- transformIndices: ['ip_met*'],
- }),
- factoryQueryType: NetworkKpiQueries.tlsHandshakesEntities,
- };
- }
- case NetworkKpiQueries.uniquePrivateIps: {
- return {
- indices: createIndicesFromPrefix({
- prefix: settings.prefix,
- transformIndices: ['src_ip_ent*', 'dest_ip_ent*'],
- }),
- factoryQueryType: NetworkKpiQueries.uniquePrivateIpsEntities,
- };
- }
- default: {
- return undefined;
- }
- }
-};
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_users.test.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_users.test.ts
deleted file mode 100644
index ae3690d72baba..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_users.test.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { UsersQueries } from '../../../common/search_strategy';
-import { getTransformChangesForUsers } from './get_transform_changes_for_users';
-import { getTransformConfigSchemaMock } from './transform_config_schema.mock';
-
-/** Get the return type of getTransformChangesForUsers for TypeScript checks against expected */
-type ReturnTypeGetTransformChangesForUsers = ReturnType;
-
-describe('get_transform_changes_for_user', () => {
- test('it gets a transform change for authentications', () => {
- expect(
- getTransformChangesForUsers({
- factoryQueryType: UsersQueries.authentications,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual({
- factoryQueryType: UsersQueries.authenticationsEntities,
- indices: ['.estc_all_user_ent*'],
- });
- });
-
- test('it returns an "undefined" for another value', () => {
- expect(
- getTransformChangesForUsers({
- factoryQueryType: UsersQueries.details,
- settings: getTransformConfigSchemaMock().settings[0],
- })
- ).toEqual(undefined);
- });
-});
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_users.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_users.ts
deleted file mode 100644
index a91bc05bb7383..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_for_users.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { UsersQueries } from '../../../common/search_strategy';
-import { createIndicesFromPrefix } from './create_indices_from_prefix';
-import { GetTransformChanges } from './types';
-
-/**
- * Given a factory query type this will return the transform changes such as the transform indices if it matches
- * the correct type, otherwise it will return "undefined"
- * @param factoryQueryType The query type to check if we have a transform for it and are capable of rendering one or not
- * @param settings The settings configuration to get the prefix from
- * @returns The transform type if we have one, otherwise undefined
- */
-export const getTransformChangesForUsers: GetTransformChanges = ({
- factoryQueryType,
- settings,
-}) => {
- switch (factoryQueryType) {
- case UsersQueries.authentications: {
- return {
- indices: createIndicesFromPrefix({
- prefix: settings.prefix,
- transformIndices: ['user_ent*'],
- }),
- factoryQueryType: UsersQueries.authenticationsEntities,
- };
- }
- default: {
- return undefined;
- }
- }
-};
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_if_they_exist.test.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_if_they_exist.test.ts
deleted file mode 100644
index 19c9ba5596027..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_if_they_exist.test.ts
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-import { getTransformChangesIfTheyExist } from './get_transform_changes_if_they_exist';
-import { HostsKpiQueries, HostsQueries } from '../../../common/search_strategy';
-import moment from 'moment';
-import { getTransformConfigSchemaMock } from './transform_config_schema.mock';
-
-/** Get the return type of createIndicesFromPrefix for TypeScript checks against expected */
-type ReturnTypeGetTransformChangesIfTheyExist = ReturnType;
-
-describe('get_transform_changes_if_they_exist', () => {
- beforeEach(() => {
- // Adds extra switch to suppress deprecation warnings that moment does not expose in TypeScript
- (
- moment as typeof moment & {
- suppressDeprecationWarnings: boolean;
- }
- ).suppressDeprecationWarnings = true;
- });
-
- afterEach(() => {
- // Adds extra switch to suppress deprecation warnings that moment does not expose in TypeScript
- (
- moment as typeof moment & {
- suppressDeprecationWarnings: boolean;
- }
- ).suppressDeprecationWarnings = false;
- });
-
- describe('transformSettings enabled conditional logic', () => {
- test('returns transformed settings if our settings is enabled', () => {
- expect(
- getTransformChangesIfTheyExist({
- factoryQueryType: HostsQueries.hosts,
- indices: ['auditbeat-*'],
- transformSettings: { ...getTransformConfigSchemaMock(), enabled: true }, // sets enabled to true
- filterQuery: undefined,
- histogramType: undefined,
- timerange: {
- to: '2021-07-06T23:49:38.643Z',
- from: '2021-07-06T20:49:38.643Z',
- interval: '5m',
- },
- })
- ).toMatchObject>({
- indices: ['.estc_all_host_ent*'],
- factoryQueryType: HostsQueries.hostsEntities,
- });
- });
-
- test('returns regular settings if our settings is disabled', () => {
- expect(
- getTransformChangesIfTheyExist({
- factoryQueryType: HostsQueries.hosts,
- indices: ['auditbeat-*'],
- transformSettings: { ...getTransformConfigSchemaMock(), enabled: false }, // sets enabled to false
- filterQuery: undefined,
- histogramType: undefined,
- timerange: {
- to: '2021-07-06T23:49:38.643Z',
- from: '2021-07-06T20:49:38.643Z',
- interval: '5m',
- },
- })
- ).toMatchObject>({
- indices: ['auditbeat-*'],
- factoryQueryType: HostsQueries.hosts,
- });
- });
- });
-
- describe('filter query compatibility conditional logic', () => {
- test('returns regular settings if filter is set to something other than match_all', () => {
- expect(
- getTransformChangesIfTheyExist({
- factoryQueryType: HostsQueries.hosts,
- indices: ['auditbeat-*'],
- transformSettings: getTransformConfigSchemaMock(),
- filterQuery: {
- bool: {
- must: [],
- filter: [{ match_none: {} }], // match_none shouldn't return transform
- should: [],
- must_not: [],
- },
- },
- histogramType: undefined,
- timerange: {
- to: '2021-07-06T23:49:38.643Z',
- from: '2021-07-06T20:49:38.643Z',
- interval: '5m',
- },
- })
- ).toMatchObject>({
- indices: ['auditbeat-*'],
- factoryQueryType: HostsQueries.hosts,
- });
- });
-
- test('returns transformed settings if filter is set to something such as match_all', () => {
- expect(
- getTransformChangesIfTheyExist({
- factoryQueryType: HostsQueries.hosts,
- indices: ['auditbeat-*'],
- transformSettings: getTransformConfigSchemaMock(),
- filterQuery: {
- bool: {
- must: [],
- filter: [{ match_all: {} }], // match_all should return transform
- should: [],
- must_not: [],
- },
- },
- histogramType: undefined,
- timerange: {
- to: '2021-07-06T23:49:38.643Z',
- from: '2021-07-06T20:49:38.643Z',
- interval: '5m',
- },
- })
- ).toMatchObject>({
- indices: ['.estc_all_host_ent*'],
- factoryQueryType: HostsQueries.hostsEntities,
- });
- });
-
- test('returns transformed settings if filter is set to undefined', () => {
- expect(
- getTransformChangesIfTheyExist({
- factoryQueryType: HostsQueries.hosts,
- indices: ['auditbeat-*'],
- transformSettings: getTransformConfigSchemaMock(),
- filterQuery: undefined, // undefined should return transform
- histogramType: undefined,
- timerange: {
- to: '2021-07-06T23:49:38.643Z',
- from: '2021-07-06T20:49:38.643Z',
- interval: '5m',
- },
- })
- ).toMatchObject>({
- indices: ['.estc_all_host_ent*'],
- factoryQueryType: HostsQueries.hostsEntities,
- });
- });
- });
-
- describe('timerange adjustments conditional logic', () => {
- test('returns regular settings if timerange is less than an hour', () => {
- expect(
- getTransformChangesIfTheyExist({
- factoryQueryType: HostsQueries.hosts,
- indices: ['auditbeat-*'],
- transformSettings: getTransformConfigSchemaMock(),
- filterQuery: undefined,
- histogramType: undefined,
- timerange: {
- to: '2021-07-06T23:49:38.643Z', // Less than hour
- from: '2021-07-06T23:39:38.643Z', // Less than hour
- interval: '5m',
- },
- })
- ).toMatchObject>({
- indices: ['auditbeat-*'],
- factoryQueryType: HostsQueries.hosts,
- });
- });
-
- test('returns regular settings if timerange is invalid', () => {
- expect(
- getTransformChangesIfTheyExist({
- factoryQueryType: HostsQueries.hosts,
- indices: ['auditbeat-*'],
- transformSettings: getTransformConfigSchemaMock(),
- filterQuery: undefined,
- histogramType: undefined,
- timerange: {
- to: 'now-invalid', // invalid to
- from: 'now-invalid2', // invalid from
- interval: '5m',
- },
- })
- ).toMatchObject>({
- indices: ['auditbeat-*'],
- factoryQueryType: HostsQueries.hosts,
- });
- });
-
- test('returns transformed settings if timerange is greater than an hour', () => {
- expect(
- getTransformChangesIfTheyExist({
- factoryQueryType: HostsQueries.hosts,
- indices: ['auditbeat-*'],
- transformSettings: getTransformConfigSchemaMock(),
- filterQuery: undefined,
- histogramType: undefined,
- timerange: {
- to: '2021-07-06T23:49:38.643Z', // Greater than an hour
- from: '2021-07-06T20:49:38.643Z', // Greater than an hour
- interval: '5m',
- },
- })
- ).toMatchObject>({
- indices: ['.estc_all_host_ent*'],
- factoryQueryType: HostsQueries.hostsEntities,
- });
- });
- });
-
- describe('settings match conditional logic', () => {
- test('it returns regular settings if settings do not match', () => {
- expect(
- getTransformChangesIfTheyExist({
- factoryQueryType: HostsQueries.hosts,
- indices: ['should-not-match-*'], // index doesn't match anything
- transformSettings: getTransformConfigSchemaMock(),
- filterQuery: undefined,
- histogramType: undefined,
- timerange: {
- to: '2021-07-06T23:49:38.643Z',
- from: '2021-07-06T20:49:38.643Z',
- interval: '5m',
- },
- })
- ).toMatchObject>({
- indices: ['should-not-match-*'],
- factoryQueryType: HostsQueries.hosts,
- });
- });
-
- test('it returns transformed settings if settings do match', () => {
- expect(
- getTransformChangesIfTheyExist({
- factoryQueryType: HostsQueries.hosts,
- indices: [
- 'auditbeat-*',
- 'endgame-*',
- 'filebeat-*',
- 'logs-*',
- 'packetbeat-*',
- 'winlogbeat-*',
- '-subtract-something',
- ],
- transformSettings: getTransformConfigSchemaMock(),
- filterQuery: undefined,
- histogramType: undefined,
- timerange: {
- to: '2021-07-06T23:49:38.643Z',
- from: '2021-07-06T20:49:38.643Z',
- interval: '5m',
- },
- })
- ).toMatchObject>({
- indices: ['.estc_all_host_ent*'],
- factoryQueryType: HostsQueries.hostsEntities,
- });
- });
- });
-
- describe('transform changes conditional logic', () => {
- test('it returns regular settings if it does not match a transform factory type', () => {
- expect(
- getTransformChangesIfTheyExist({
- factoryQueryType: HostsQueries.firstOrLastSeen, // query type not used for any transforms yet
- indices: ['auditbeat-*'],
- transformSettings: getTransformConfigSchemaMock(),
- filterQuery: undefined,
- histogramType: undefined,
- timerange: {
- to: '2021-07-06T23:49:38.643Z',
- from: '2021-07-06T20:49:38.643Z',
- interval: '5m',
- },
- })
- ).toMatchObject>({
- indices: ['auditbeat-*'],
- factoryQueryType: HostsQueries.firstOrLastSeen,
- });
- });
-
- test('it returns transformed settings if it does match a transform factory type', () => {
- expect(
- getTransformChangesIfTheyExist({
- factoryQueryType: HostsKpiQueries.kpiHosts, // valid kpiHosts for a transform
- indices: ['auditbeat-*'],
- transformSettings: getTransformConfigSchemaMock(),
- filterQuery: undefined,
- histogramType: undefined,
- timerange: {
- to: '2021-07-06T23:49:38.643Z',
- from: '2021-07-06T20:49:38.643Z',
- interval: '5m',
- },
- })
- ).toMatchObject>({
- indices: ['.estc_all_host_ent*'],
- factoryQueryType: HostsKpiQueries.kpiHostsEntities,
- });
- });
- });
-});
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_if_they_exist.ts b/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_if_they_exist.ts
deleted file mode 100644
index 20e0b6a31d2c3..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/get_transform_changes_if_they_exist.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { adjustTimeRange } from './adjust_timerange';
-import { getSettingsMatch } from './get_settings_match';
-import { getTransformChanges } from './get_transform_changes';
-import { isFilterQueryCompatible } from './is_filter_query_compatible';
-import { GetTransformChangesIfTheyExist } from './types';
-
-// TODO: Add the other switches here such as the disabling of a widget/factory type
-// or if a transform is disabled, then this cannot use the query
-export const getTransformChangesIfTheyExist: GetTransformChangesIfTheyExist = ({
- factoryQueryType,
- indices,
- transformSettings,
- filterQuery,
- histogramType,
- timerange,
-}) => {
- if (!transformSettings.enabled) {
- // Early return if we are not enabled
- return { factoryQueryType, indices, timerange };
- }
-
- if (!isFilterQueryCompatible(filterQuery)) {
- // Early return if the filter query is not compatible
- return { factoryQueryType, indices, timerange };
- }
-
- const { timeRangeAdjusted, duration } = adjustTimeRange(timerange);
-
- if (timeRangeAdjusted == null || duration == null || duration.asHours() < 1) {
- // Early return if we are less than hour of time or from is something not as we expect
- // and as we should just use raw events instead of summaries
- return { factoryQueryType, indices, timerange };
- }
-
- const settings = getSettingsMatch({ indices, transformSettings });
- if (settings == null) {
- // early return if none of the settings match
- return { factoryQueryType, indices, timerange };
- }
-
- const transform = getTransformChanges({ factoryQueryType, settings, histogramType });
- if (transform) {
- return { ...transform, timerange: timeRangeAdjusted };
- }
-
- // nothing matched, return what was sent in unchanged
- return { factoryQueryType, indices, timerange };
-};
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/index.ts b/x-pack/plugins/security_solution/public/transforms/utils/index.ts
deleted file mode 100644
index 8cacb0035204a..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/index.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-export * from './adjust_timerange';
-export * from './create_indices_from_prefix';
-export * from './get_settings_match';
-export * from './get_transform_changes_for_hosts';
-export * from './get_transform_changes_for_kpi';
-export * from './get_transform_changes_for_matrix_histogram';
-export * from './get_transform_changes_for_network';
-export * from './get_transform_changes_if_they_exist';
-export * from './get_transform_changes';
-export * from './is_filter_query_compatible';
-export * from './types';
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/is_filter_query_compatible.test.ts b/x-pack/plugins/security_solution/public/transforms/utils/is_filter_query_compatible.test.ts
deleted file mode 100644
index 74dd1373a4d39..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/is_filter_query_compatible.test.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { isFilterQueryCompatible } from './is_filter_query_compatible';
-
-describe('is_filter_query_compatible', () => {
- test('returns true if given an undefined', () => {
- expect(isFilterQueryCompatible(undefined)).toEqual(true);
- });
-
- test('returns "true" if given a match all object', () => {
- expect(
- isFilterQueryCompatible({
- bool: {
- must: [],
- filter: [{ match_all: {} }],
- should: [],
- must_not: [],
- },
- })
- ).toEqual(true);
- });
-
- test('returns "false" if given a match all object with something inside of it such as match_none', () => {
- expect(
- isFilterQueryCompatible({
- bool: {
- must: [],
- filter: [{ match_none: {} }],
- should: [],
- must_not: [],
- },
- })
- ).toEqual(false);
- });
-
- test('returns "true" if given empty array for a filter', () => {
- expect(
- isFilterQueryCompatible({
- bool: {
- must: [],
- filter: [],
- should: [],
- must_not: [],
- },
- })
- ).toEqual(true);
- });
-
- test('returns "true" if given match all object as a string', () => {
- expect(
- isFilterQueryCompatible(
- JSON.stringify({
- bool: {
- must: [],
- filter: [],
- should: [],
- must_not: [],
- },
- })
- )
- ).toEqual(true);
- });
-
- test('returns "true" if given empty array for a filter as a string', () => {
- expect(
- isFilterQueryCompatible(
- JSON.stringify({
- bool: {
- must: [],
- filter: [],
- should: [],
- must_not: [],
- },
- })
- )
- ).toEqual(true);
- });
-
- test('returns "false" if given an invalid string', () => {
- expect(isFilterQueryCompatible('invalid string')).toEqual(false);
- });
-});
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/is_filter_query_compatible.ts b/x-pack/plugins/security_solution/public/transforms/utils/is_filter_query_compatible.ts
deleted file mode 100644
index 2f2c9ee7f2deb..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/is_filter_query_compatible.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { isEqual } from 'lodash/fp';
-import { ESQuery } from '../../../common/typed_json';
-
-/**
- * Array of query compatible objects which are at the moment all
- * simple empty or match all based objects
- */
-const queryCompatibleStrings: ESQuery[] = [
- {
- bool: {
- must: [],
- filter: [{ match_all: {} }],
- should: [],
- must_not: [],
- },
- },
- {
- bool: {
- must: [],
- filter: [],
- should: [],
- must_not: [],
- },
- },
-];
-
-/**
- * Returns true if the filter query matches against one of the compatible strings, otherwise
- * false. Right now we only check if the filter query is empty, or a match all in order to activate
- * the transform.
- * @param filterQuery The filterQuery to check against and return true if it matches, otherwise false.
- * @returns true if the filter is compatible, otherwise false.
- */
-export const isFilterQueryCompatible = (filterQuery: ESQuery | string | undefined): boolean => {
- if (filterQuery === undefined) {
- return true;
- } else if (typeof filterQuery === 'string') {
- try {
- const filterQueryObject = JSON.parse(filterQuery);
- return queryCompatibleStrings.some((entry) => isEqual(entry, filterQueryObject));
- } catch (error) {
- return false;
- }
- } else {
- return queryCompatibleStrings.some((entry) => isEqual(entry, filterQuery));
- }
-};
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/transform_config_schema.mock.ts b/x-pack/plugins/security_solution/public/transforms/utils/transform_config_schema.mock.ts
deleted file mode 100644
index ef3d4bfe6f007..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/transform_config_schema.mock.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-import { TransformConfigSchema } from '../../../common/transforms/types';
-
-/**
- * Mock for the TransformConfigSchema.
- * @returns A transform config schema mock
- */
-export const getTransformConfigSchemaMock = (): TransformConfigSchema => ({
- enabled: true,
- auto_start: true,
- auto_create: true,
- query: {
- range: {
- '@timestamp': {
- gte: 'now-1d/d',
- format: 'strict_date_optional_time',
- },
- },
- },
- retention_policy: {
- time: {
- field: '@timestamp',
- max_age: '1w',
- },
- },
- max_page_search_size: 5000,
- settings: [
- {
- prefix: 'all',
- indices: ['auditbeat-*', 'endgame-*', 'filebeat-*', 'logs-*', 'packetbeat-*', 'winlogbeat-*'],
- data_sources: [
- ['auditbeat-*', 'endgame-*', 'filebeat-*', 'logs-*', 'packetbeat-*', 'winlogbeat-*'],
- ['auditbeat-*', 'filebeat-*', 'logs-*', 'winlogbeat-*'],
- ['auditbeat-*'],
- ],
- },
- ],
-});
diff --git a/x-pack/plugins/security_solution/public/transforms/utils/types.ts b/x-pack/plugins/security_solution/public/transforms/utils/types.ts
deleted file mode 100644
index 96dc1ee228bd0..0000000000000
--- a/x-pack/plugins/security_solution/public/transforms/utils/types.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { TimerangeInput } from '../../../common/search_strategy/common';
-import { ESQuery } from '../../../common/typed_json';
-import { TransformConfigSchema } from '../../../common/transforms/types';
-import {
- FactoryQueryTypes,
- MatrixHistogramType,
-} from '../../../common/search_strategy/security_solution';
-
-export type GetTransformChanges = ({
- factoryQueryType,
- settings,
- histogramType,
-}: {
- factoryQueryType: FactoryQueryTypes;
- settings: TransformConfigSchema['settings'][0];
- histogramType?: MatrixHistogramType;
-}) =>
- | {
- indices: string[];
- factoryQueryType: FactoryQueryTypes;
- histogramType?: MatrixHistogramType;
- }
- | undefined;
-
-export type GetTransformChangesIfTheyExist = ({
- factoryQueryType,
- indices,
- filterQuery,
- histogramType,
- timerange,
-}: {
- factoryQueryType: FactoryQueryTypes;
- indices: string[];
- transformSettings: TransformConfigSchema;
- filterQuery: ESQuery | string | undefined;
- histogramType?: MatrixHistogramType;
- timerange: TimerangeInput;
-}) => {
- indices: string[];
- factoryQueryType: FactoryQueryTypes;
- histogramType?: MatrixHistogramType;
- timerange: TimerangeInput;
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.ts
index d936ffdefb6c2..d05b9e1f8fb1a 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.ts
@@ -29,7 +29,6 @@ import { buildHostsQuery } from './query.all_hosts.dsl';
import { formatHostEdgesData, HOSTS_FIELDS } from './helpers';
import { IScopedClusterClient } from '../../../../../../../../../src/core/server';
-import { buildHostsQueryEntities } from './query.all_hosts_entities.dsl';
import { EndpointAppContext } from '../../../../../endpoint/types';
import { buildRiskScoreQuery } from '../../risk_score/all/query.risk_score.dsl';
@@ -132,43 +131,3 @@ async function getHostRiskData(
return undefined;
}
}
-
-export const allHostsEntities: SecuritySolutionFactory = {
- buildDsl: (options: HostsRequestOptions) => {
- if (options.pagination && options.pagination.querySize >= DEFAULT_MAX_TABLE_QUERY_SIZE) {
- throw new Error(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`);
- }
- return buildHostsQueryEntities(options);
- },
- parse: async (
- options: HostsRequestOptions,
- response: IEsSearchResponse
- ): Promise => {
- const { activePage, cursorStart, fakePossibleCount, querySize } = options.pagination;
- const totalCount = getOr(0, 'aggregations.host_count.value', response.rawResponse);
- const buckets: HostAggEsItem[] = getOr(
- [],
- 'aggregations.host_data.buckets',
- response.rawResponse
- );
- const hostsEdges = buckets.map((bucket) => formatHostEdgesData(HOSTS_FIELDS, bucket));
- const fakeTotalCount = fakePossibleCount <= totalCount ? fakePossibleCount : totalCount;
- const edges = hostsEdges.splice(cursorStart, querySize - cursorStart);
- const inspect = {
- dsl: [inspectStringifyObject(buildHostsQueryEntities(options))],
- };
- const showMorePagesIndicator = totalCount > fakeTotalCount;
-
- return {
- ...response,
- inspect,
- edges,
- totalCount,
- pageInfo: {
- activePage: activePage ?? 0,
- fakeTotalCount,
- showMorePagesIndicator,
- },
- };
- },
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/query.all_hosts_entities.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/query.all_hosts_entities.dsl.ts
deleted file mode 100644
index 73f35091ae093..0000000000000
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/query.all_hosts_entities.dsl.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { isEmpty } from 'lodash/fp';
-import type { ISearchRequestParams } from '../../../../../../../../../src/plugins/data/common';
-import {
- Direction,
- HostsRequestOptions,
- SortField,
- HostsFields,
-} from '../../../../../../common/search_strategy';
-import { createQueryFilterClauses } from '../../../../../utils/build_query';
-import { assertUnreachable } from '../../../../../../common/utility_types';
-
-export const buildHostsQueryEntities = ({
- defaultIndex,
- docValueFields,
- filterQuery,
- pagination: { querySize },
- sort,
- timerange: { from, to },
-}: HostsRequestOptions): ISearchRequestParams => {
- const filter = [
- ...createQueryFilterClauses(filterQuery),
- {
- range: {
- '@timestamp': {
- gte: from,
- lte: to,
- format: 'strict_date_optional_time',
- },
- },
- },
- ];
-
- const agg = { host_count: { cardinality: { field: 'host.name' } } };
-
- const dslQuery = {
- allow_no_indices: true,
- index: defaultIndex,
- ignore_unavailable: true,
- track_total_hits: false,
- body: {
- ...(!isEmpty(docValueFields) ? { docvalue_fields: docValueFields } : {}),
- aggregations: {
- ...agg,
- host_data: {
- terms: { size: querySize, field: 'host.name', order: getQueryOrder(sort) },
- aggs: {
- lastSeen: { max: { field: '@timestamp' } },
- os: {
- top_hits: {
- size: 1,
- sort: [
- {
- '@timestamp': {
- order: 'desc' as const,
- },
- },
- ],
- _source: {
- includes: ['host.os.*'],
- },
- },
- },
- },
- },
- },
- query: { bool: { filter } },
- size: 0,
- },
- };
-
- return dslQuery;
-};
-
-type QueryOrder = { lastSeen: Direction } | { _key: Direction };
-
-const getQueryOrder = (sort: SortField): QueryOrder => {
- switch (sort.field) {
- case HostsFields.lastSeen:
- return { lastSeen: sort.direction };
- case HostsFields.hostName:
- return { _key: sort.direction };
- default:
- return assertUnreachable(sort.field);
- }
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.test.ts
index 901d577fdbf5a..3cac14fb56f80 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.test.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.test.ts
@@ -13,9 +13,9 @@ import { hostOverview } from './overview';
import { firstOrLastSeenHost } from './last_first_seen';
import { uncommonProcesses } from './uncommon_processes';
-import { hostsKpiAuthentications, hostsKpiAuthenticationsEntities } from './kpi/authentications';
-import { hostsKpiHosts, hostsKpiHostsEntities } from './kpi/hosts';
-import { hostsKpiUniqueIps, hostsKpiUniqueIpsEntities } from './kpi/unique_ips';
+import { hostsKpiAuthentications } from './kpi/authentications';
+import { hostsKpiHosts } from './kpi/hosts';
+import { hostsKpiUniqueIps } from './kpi/unique_ips';
jest.mock('./all');
jest.mock('./details');
@@ -35,10 +35,7 @@ describe('hostsFactory', () => {
[HostsQueries.firstOrLastSeen]: firstOrLastSeenHost,
[HostsQueries.uncommonProcesses]: uncommonProcesses,
[HostsKpiQueries.kpiAuthentications]: hostsKpiAuthentications,
- [HostsKpiQueries.kpiAuthenticationsEntities]: hostsKpiAuthenticationsEntities,
[HostsKpiQueries.kpiHosts]: hostsKpiHosts,
- [HostsKpiQueries.kpiHostsEntities]: hostsKpiHostsEntities,
- [HostsKpiQueries.kpiUniqueIpsEntities]: hostsKpiUniqueIpsEntities,
[HostsKpiQueries.kpiUniqueIps]: hostsKpiUniqueIps,
};
expect(hostsFactory).toEqual(expectedHostsFactory);
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.ts
index 5d40e5e153599..d7a37f871e252 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.ts
@@ -12,14 +12,14 @@ import {
} from '../../../../../common/search_strategy/security_solution';
import { SecuritySolutionFactory } from '../types';
-import { allHosts, allHostsEntities } from './all';
+import { allHosts } from './all';
import { hostDetails } from './details';
import { hostOverview } from './overview';
import { firstOrLastSeenHost } from './last_first_seen';
import { uncommonProcesses } from './uncommon_processes';
-import { hostsKpiAuthentications, hostsKpiAuthenticationsEntities } from './kpi/authentications';
-import { hostsKpiHosts, hostsKpiHostsEntities } from './kpi/hosts';
-import { hostsKpiUniqueIps, hostsKpiUniqueIpsEntities } from './kpi/unique_ips';
+import { hostsKpiAuthentications } from './kpi/authentications';
+import { hostsKpiHosts } from './kpi/hosts';
+import { hostsKpiUniqueIps } from './kpi/unique_ips';
export const hostsFactory: Record<
HostsQueries | HostsKpiQueries,
@@ -27,14 +27,10 @@ export const hostsFactory: Record<
> = {
[HostsQueries.details]: hostDetails,
[HostsQueries.hosts]: allHosts,
- [HostsQueries.hostsEntities]: allHostsEntities,
[HostsQueries.overview]: hostOverview,
[HostsQueries.firstOrLastSeen]: firstOrLastSeenHost,
[HostsQueries.uncommonProcesses]: uncommonProcesses,
[HostsKpiQueries.kpiAuthentications]: hostsKpiAuthentications,
- [HostsKpiQueries.kpiAuthenticationsEntities]: hostsKpiAuthenticationsEntities,
[HostsKpiQueries.kpiHosts]: hostsKpiHosts,
- [HostsKpiQueries.kpiHostsEntities]: hostsKpiHostsEntities,
[HostsKpiQueries.kpiUniqueIps]: hostsKpiUniqueIps,
- [HostsKpiQueries.kpiUniqueIpsEntities]: hostsKpiUniqueIpsEntities,
};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/authentications/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/authentications/helpers.ts
index 6b81dd177bbf6..34b4a682d42de 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/authentications/helpers.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/authentications/helpers.ts
@@ -20,13 +20,3 @@ export const formatAuthenticationsHistogramData = (
y: count.doc_count,
}))
: null;
-
-export const formatAuthenticationsHistogramDataEntities = (
- data: Array>
-): HostsKpiHistogramData[] | null =>
- data && data.length > 0
- ? data.map(({ key, count }) => ({
- x: key,
- y: count.value,
- }))
- : null;
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/authentications/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/authentications/index.ts
index 1512dc1b7da61..d6a1e1a8ac7ec 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/authentications/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/authentications/index.ts
@@ -16,11 +16,7 @@ import {
import { inspectStringifyObject } from '../../../../../../utils/build_query';
import { SecuritySolutionFactory } from '../../../types';
import { buildHostsKpiAuthenticationsQuery } from './query.hosts_kpi_authentications.dsl';
-import {
- formatAuthenticationsHistogramData,
- formatAuthenticationsHistogramDataEntities,
-} from './helpers';
-import { buildHostsKpiAuthenticationsQueryEntities } from './query.hosts_kpi_authentications_entities.dsl';
+import { formatAuthenticationsHistogramData } from './helpers';
export const hostsKpiAuthentications: SecuritySolutionFactory =
{
@@ -67,49 +63,3 @@ export const hostsKpiAuthentications: SecuritySolutionFactory =
- {
- buildDsl: (options: HostsKpiAuthenticationsRequestOptions) =>
- buildHostsKpiAuthenticationsQueryEntities(options),
- parse: async (
- options: HostsKpiAuthenticationsRequestOptions,
- response: IEsSearchResponse
- ): Promise => {
- const inspect = {
- dsl: [inspectStringifyObject(buildHostsKpiAuthenticationsQueryEntities(options))],
- };
-
- const authenticationsSuccessHistogram = getOr(
- null,
- 'aggregations.authentication_success_histogram.buckets',
- response.rawResponse
- );
- const authenticationsFailureHistogram = getOr(
- null,
- 'aggregations.authentication_failure_histogram.buckets',
- response.rawResponse
- );
-
- return {
- ...response,
- inspect,
- authenticationsSuccess: getOr(
- null,
- 'aggregations.authentication_success.value',
- response.rawResponse
- ),
- authenticationsSuccessHistogram: formatAuthenticationsHistogramDataEntities(
- authenticationsSuccessHistogram
- ),
- authenticationsFailure: getOr(
- null,
- 'aggregations.authentication_failure.value',
- response.rawResponse
- ),
- authenticationsFailureHistogram: formatAuthenticationsHistogramDataEntities(
- authenticationsFailureHistogram
- ),
- };
- },
- };
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/authentications/query.hosts_kpi_authentications_entities.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/authentications/query.hosts_kpi_authentications_entities.dsl.ts
deleted file mode 100644
index fd1104345babc..0000000000000
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/authentications/query.hosts_kpi_authentications_entities.dsl.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { HostsKpiAuthenticationsRequestOptions } from '../../../../../../../common/search_strategy/security_solution/hosts';
-import { createQueryFilterClauses } from '../../../../../../utils/build_query';
-
-export const buildHostsKpiAuthenticationsQueryEntities = ({
- filterQuery,
- timerange: { from, to },
- defaultIndex,
-}: HostsKpiAuthenticationsRequestOptions) => {
- const filter = [
- ...createQueryFilterClauses(filterQuery),
- {
- range: {
- '@timestamp': {
- gte: from,
- lte: to,
- format: 'strict_date_optional_time',
- },
- },
- },
- ];
-
- const dslQuery = {
- index: defaultIndex,
- allow_no_indices: true,
- ignore_unavailable: true,
- track_total_hits: false,
- body: {
- aggs: {
- authentication_success: {
- sum: {
- field: 'metrics.event.authentication.success.value_count',
- },
- },
- authentication_success_histogram: {
- auto_date_histogram: {
- field: '@timestamp',
- buckets: 6,
- },
- aggs: {
- count: {
- sum: {
- field: 'metrics.event.authentication.success.value_count',
- },
- },
- },
- },
- authentication_failure: {
- sum: {
- field: 'metrics.event.authentication.failure.value_count',
- },
- },
- authentication_failure_histogram: {
- auto_date_histogram: {
- field: '@timestamp',
- buckets: 6,
- },
- aggs: {
- count: {
- sum: {
- field: 'metrics.event.authentication.failure.value_count',
- },
- },
- },
- },
- },
- query: {
- bool: {
- filter,
- },
- },
- size: 0,
- },
- };
-
- return dslQuery;
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/index.ts
index a8082822b2775..c4714e81c6ec4 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/index.ts
@@ -17,7 +17,6 @@ import { inspectStringifyObject } from '../../../../../../utils/build_query';
import { SecuritySolutionFactory } from '../../../types';
import { buildHostsKpiHostsQuery } from './query.hosts_kpi_hosts.dsl';
import { formatGeneralHistogramData } from '../common';
-import { buildHostsKpiHostsQueryEntities } from './query.hosts_kpi_hosts_entities.dsl';
export const hostsKpiHosts: SecuritySolutionFactory = {
buildDsl: (options: HostsKpiHostsRequestOptions) => buildHostsKpiHostsQuery(options),
@@ -42,27 +41,3 @@ export const hostsKpiHosts: SecuritySolutionFactory =
};
},
};
-
-export const hostsKpiHostsEntities: SecuritySolutionFactory = {
- buildDsl: (options: HostsKpiHostsRequestOptions) => buildHostsKpiHostsQueryEntities(options),
- parse: async (
- options: HostsKpiHostsRequestOptions,
- response: IEsSearchResponse
- ): Promise => {
- const inspect = {
- dsl: [inspectStringifyObject(buildHostsKpiHostsQueryEntities(options))],
- };
-
- const hostsHistogram = getOr(
- null,
- 'aggregations.hosts_histogram.buckets',
- response.rawResponse
- );
- return {
- ...response,
- inspect,
- hosts: getOr(null, 'aggregations.hosts.value', response.rawResponse),
- hostsHistogram: formatGeneralHistogramData(hostsHistogram),
- };
- },
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/query.hosts_kpi_hosts_entities.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/query.hosts_kpi_hosts_entities.dsl.ts
deleted file mode 100644
index 785f6aa5b6980..0000000000000
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/query.hosts_kpi_hosts_entities.dsl.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { HostsKpiHostsRequestOptions } from '../../../../../../../common/search_strategy/security_solution/hosts';
-import { createQueryFilterClauses } from '../../../../../../utils/build_query';
-
-export const buildHostsKpiHostsQueryEntities = ({
- filterQuery,
- timerange: { from, to },
- defaultIndex,
-}: HostsKpiHostsRequestOptions) => {
- const filter = [
- ...createQueryFilterClauses(filterQuery),
- {
- range: {
- '@timestamp': {
- gte: from,
- lte: to,
- format: 'strict_date_optional_time',
- },
- },
- },
- ];
-
- const dslQuery = {
- index: defaultIndex,
- allow_no_indices: true,
- ignore_unavailable: true,
- track_total_hits: false,
- body: {
- aggregations: {
- hosts: {
- cardinality: {
- field: 'host.name',
- },
- },
- hosts_histogram: {
- auto_date_histogram: {
- field: '@timestamp',
- buckets: 6,
- },
- aggs: {
- count: {
- cardinality: {
- field: 'host.name',
- },
- },
- },
- },
- },
- query: {
- bool: {
- filter,
- },
- },
- size: 0,
- },
- };
-
- return dslQuery;
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/index.ts
index b81d9a4d2322b..17eceea840029 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/index.ts
@@ -17,7 +17,6 @@ import { inspectStringifyObject } from '../../../../../../utils/build_query';
import { SecuritySolutionFactory } from '../../../types';
import { buildHostsKpiUniqueIpsQuery } from './query.hosts_kpi_unique_ips.dsl';
import { formatGeneralHistogramData } from '../common';
-import { buildHostsKpiUniqueIpsQueryEntities } from './query.hosts_kpi_unique_ips_entities.dsl';
export const hostsKpiUniqueIps: SecuritySolutionFactory = {
buildDsl: (options: HostsKpiUniqueIpsRequestOptions) => buildHostsKpiUniqueIpsQuery(options),
@@ -55,41 +54,3 @@ export const hostsKpiUniqueIps: SecuritySolutionFactory = {
- buildDsl: (options: HostsKpiUniqueIpsRequestOptions) =>
- buildHostsKpiUniqueIpsQueryEntities(options),
- parse: async (
- options: HostsKpiUniqueIpsRequestOptions,
- response: IEsSearchResponse
- ): Promise => {
- const inspect = {
- dsl: [inspectStringifyObject(buildHostsKpiUniqueIpsQueryEntities(options))],
- };
-
- const uniqueSourceIpsHistogram = getOr(
- null,
- 'aggregations.unique_source_ips_histogram.buckets',
- response.rawResponse
- );
-
- const uniqueDestinationIpsHistogram = getOr(
- null,
- 'aggregations.unique_destination_ips_histogram.buckets',
- response.rawResponse
- );
-
- return {
- ...response,
- inspect,
- uniqueSourceIps: getOr(null, 'aggregations.unique_source_ips.value', response.rawResponse),
- uniqueSourceIpsHistogram: formatGeneralHistogramData(uniqueSourceIpsHistogram),
- uniqueDestinationIps: getOr(
- null,
- 'aggregations.unique_destination_ips.value',
- response.rawResponse
- ),
- uniqueDestinationIpsHistogram: formatGeneralHistogramData(uniqueDestinationIpsHistogram),
- };
- },
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/query.hosts_kpi_unique_ips_entities.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/query.hosts_kpi_unique_ips_entities.dsl.ts
deleted file mode 100644
index e323de78a0459..0000000000000
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/query.hosts_kpi_unique_ips_entities.dsl.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { HostsKpiUniqueIpsRequestOptions } from '../../../../../../../common/search_strategy/security_solution/hosts';
-import { createQueryFilterClauses } from '../../../../../../utils/build_query';
-
-export const buildHostsKpiUniqueIpsQueryEntities = ({
- filterQuery,
- timerange: { from, to },
- defaultIndex,
-}: HostsKpiUniqueIpsRequestOptions) => {
- const filter = [
- ...createQueryFilterClauses(filterQuery),
- {
- range: {
- '@timestamp': {
- gte: from,
- lte: to,
- format: 'strict_date_optional_time',
- },
- },
- },
- ];
-
- const dslQuery = {
- index: defaultIndex,
- allow_no_indices: true,
- ignore_unavailable: true,
- track_total_hits: false,
- body: {
- aggregations: {
- unique_source_ips: {
- cardinality: {
- field: 'source.ip',
- },
- },
- unique_source_ips_histogram: {
- auto_date_histogram: {
- field: '@timestamp',
- buckets: 6,
- },
- aggs: {
- count: {
- cardinality: {
- field: 'source.ip',
- },
- },
- },
- },
- unique_destination_ips: {
- cardinality: {
- field: 'destination.ip',
- },
- },
- unique_destination_ips_histogram: {
- auto_date_histogram: {
- field: '@timestamp',
- buckets: 6,
- },
- aggs: {
- count: {
- cardinality: {
- field: 'destination.ip',
- },
- },
- },
- },
- },
- query: {
- bool: {
- filter,
- },
- },
- size: 0,
- },
- };
-
- return dslQuery;
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/index.ts
index bde058942f2bb..377cd0a019d3f 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/index.ts
@@ -6,19 +6,10 @@
*/
import { MatrixHistogramTypeToAggName } from '../../../../../../common/search_strategy';
-import { getEntitiesParser } from '../helpers';
import { buildAuthenticationsHistogramQuery } from './query.authentications_histogram.dsl';
-import { buildAuthenticationsHistogramQueryEntities } from './query.authentications_histogram_entities.dsl';
export const authenticationsMatrixHistogramConfig = {
buildDsl: buildAuthenticationsHistogramQuery,
aggName: MatrixHistogramTypeToAggName.authentications,
parseKey: 'events.buckets',
};
-
-export const authenticationsMatrixHistogramEntitiesConfig = {
- buildDsl: buildAuthenticationsHistogramQueryEntities,
- aggName: MatrixHistogramTypeToAggName.authenticationsEntities,
- parseKey: 'events.buckets',
- parser: getEntitiesParser,
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/query.authentications_histogram_entities.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/query.authentications_histogram_entities.dsl.ts
deleted file mode 100644
index 886dcf11123bd..0000000000000
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/query.authentications_histogram_entities.dsl.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import moment from 'moment';
-
-import { createQueryFilterClauses } from '../../../../../utils/build_query';
-import { MatrixHistogramRequestOptions } from '../../../../../../common/search_strategy/security_solution/matrix_histogram';
-
-export const buildAuthenticationsHistogramQueryEntities = ({
- filterQuery,
- timerange: { from, to },
- defaultIndex,
- stackByField = 'event.outcome', // TODO: Remove this field if not used
-}: MatrixHistogramRequestOptions) => {
- const filter = [
- ...createQueryFilterClauses(filterQuery),
- {
- range: {
- '@timestamp': {
- gte: from,
- lte: to,
- format: 'strict_date_optional_time',
- },
- },
- },
- ];
-
- const getHistogramAggregation = () => {
- const histogramTimestampField = '@timestamp';
- const dateHistogram = {
- date_histogram: {
- field: histogramTimestampField,
- calendar_interval: '1h',
- min_doc_count: 0,
- extended_bounds: {
- min: moment(from).valueOf(),
- max: moment(to).valueOf(),
- },
- },
- aggs: {
- failure: {
- sum: {
- field: 'metrics.event.authentication.failure.value_count',
- },
- },
- success: {
- sum: {
- field: 'metrics.event.authentication.success.value_count',
- },
- },
- },
- };
- return { events: dateHistogram };
- };
-
- const dslQuery = {
- index: defaultIndex,
- allow_no_indices: true,
- ignore_unavailable: true,
- track_total_hits: true,
- body: {
- aggregations: getHistogramAggregation(),
- query: {
- bool: {
- filter,
- },
- },
- size: 0,
- },
- };
-
- return dslQuery;
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/helpers.ts
index c8ede95d166c7..aa6b85d795443 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/helpers.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/helpers.ts
@@ -32,19 +32,3 @@ export const getGenericData = (
return result;
};
-
-export const getEntitiesParser = (
- data: MatrixHistogramParseData,
- keyBucket: string // TODO: Remove this keyBucket if it is not being used.
-): MatrixHistogramData[] => {
- let result: MatrixHistogramData[] = [];
- data.forEach((bucketData: unknown) => {
- const successValue = get('success.value', bucketData);
- const failureValue = get('failure.value', bucketData);
- const key = get('key', bucketData);
- const histDataSuccess = { x: key, y: successValue, g: 'success' };
- const histDataFailure = { x: key, y: failureValue, g: 'failure' };
- result = [...result, histDataFailure, histDataSuccess];
- });
- return result;
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/index.ts
index db9fcc6067a74..06405fb74bc0f 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/index.ts
@@ -15,17 +15,13 @@ import {
MatrixHistogramQuery,
MatrixHistogramType,
MatrixHistogramDataConfig,
- MatrixHistogramQueryEntities,
} from '../../../../../common/search_strategy/security_solution';
import { inspectStringifyObject } from '../../../../utils/build_query';
import { SecuritySolutionFactory } from '../types';
import { getGenericData } from './helpers';
import { alertsMatrixHistogramConfig } from './alerts';
import { anomaliesMatrixHistogramConfig } from './anomalies';
-import {
- authenticationsMatrixHistogramConfig,
- authenticationsMatrixHistogramEntitiesConfig,
-} from './authentications';
+import { authenticationsMatrixHistogramConfig } from './authentications';
import { dnsMatrixHistogramConfig } from './dns';
import { eventsMatrixHistogramConfig } from './events';
import { previewMatrixHistogramConfig } from './preview';
@@ -34,7 +30,6 @@ const matrixHistogramConfig: MatrixHistogramDataConfig = {
[MatrixHistogramType.alerts]: alertsMatrixHistogramConfig,
[MatrixHistogramType.anomalies]: anomaliesMatrixHistogramConfig,
[MatrixHistogramType.authentications]: authenticationsMatrixHistogramConfig,
- [MatrixHistogramType.authenticationsEntities]: authenticationsMatrixHistogramEntitiesConfig,
[MatrixHistogramType.dns]: dnsMatrixHistogramConfig,
[MatrixHistogramType.events]: eventsMatrixHistogramConfig,
[MatrixHistogramType.preview]: previewMatrixHistogramConfig,
@@ -113,9 +108,8 @@ export const matrixHistogramEntities: SecuritySolutionFactory
> = {
[MatrixHistogramQuery]: matrixHistogram,
- [MatrixHistogramQueryEntities]: matrixHistogramEntities,
};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.test.ts
index 3e770cbedaed6..d3621ef22bf2a 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.test.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.test.ts
@@ -19,14 +19,11 @@ import { networkTls } from './tls';
import { networkTopCountries } from './top_countries';
import { networkTopNFlow } from './top_n_flow';
import { networkUsers } from './users';
-import { networkKpiDns, networkKpiDnsEntities } from './kpi/dns';
-import { networkKpiNetworkEvents, networkKpiNetworkEventsEntities } from './kpi/network_events';
-import { networkKpiTlsHandshakes, networkKpiTlsHandshakesEntities } from './kpi/tls_handshakes';
+import { networkKpiDns } from './kpi/dns';
+import { networkKpiNetworkEvents } from './kpi/network_events';
+import { networkKpiTlsHandshakes } from './kpi/tls_handshakes';
import { networkKpiUniqueFlows } from './kpi/unique_flows';
-import {
- networkKpiUniquePrivateIps,
- networkKpiUniquePrivateIpsEntities,
-} from './kpi/unique_private_ips';
+import { networkKpiUniquePrivateIps } from './kpi/unique_private_ips';
jest.mock('./details');
jest.mock('./dns');
@@ -54,14 +51,10 @@ describe('networkFactory', () => {
[NetworkQueries.topNFlow]: networkTopNFlow,
[NetworkQueries.users]: networkUsers,
[NetworkKpiQueries.dns]: networkKpiDns,
- [NetworkKpiQueries.dnsEntities]: networkKpiDnsEntities,
[NetworkKpiQueries.networkEvents]: networkKpiNetworkEvents,
- [NetworkKpiQueries.networkEventsEntities]: networkKpiNetworkEventsEntities,
- [NetworkKpiQueries.tlsHandshakesEntities]: networkKpiTlsHandshakesEntities,
[NetworkKpiQueries.tlsHandshakes]: networkKpiTlsHandshakes,
[NetworkKpiQueries.uniqueFlows]: networkKpiUniqueFlows,
[NetworkKpiQueries.uniquePrivateIps]: networkKpiUniquePrivateIps,
- [NetworkKpiQueries.uniquePrivateIpsEntities]: networkKpiUniquePrivateIpsEntities,
};
expect(networkFactory).toEqual(expectedNetworkFactory);
});
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.ts
index 3a7c4951ea878..9d9940247eb30 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.ts
@@ -11,22 +11,19 @@ import {
NetworkKpiQueries,
} from '../../../../../common/search_strategy/security_solution';
-import { networkKpiDns, networkKpiDnsEntities } from './kpi/dns';
-import { networkKpiNetworkEvents, networkKpiNetworkEventsEntities } from './kpi/network_events';
-import { networkKpiTlsHandshakes, networkKpiTlsHandshakesEntities } from './kpi/tls_handshakes';
+import { networkKpiDns } from './kpi/dns';
+import { networkKpiNetworkEvents } from './kpi/network_events';
+import { networkKpiTlsHandshakes } from './kpi/tls_handshakes';
import { networkKpiUniqueFlows } from './kpi/unique_flows';
-import {
- networkKpiUniquePrivateIps,
- networkKpiUniquePrivateIpsEntities,
-} from './kpi/unique_private_ips';
+import { networkKpiUniquePrivateIps } from './kpi/unique_private_ips';
import { SecuritySolutionFactory } from '../types';
import { networkDetails } from './details';
import { networkDns } from './dns';
import { networkHttp } from './http';
import { networkOverview } from './overview';
import { networkTls } from './tls';
-import { networkTopCountries, networkTopCountriesEntities } from './top_countries';
-import { networkTopNFlow, networkTopNFlowEntities } from './top_n_flow';
+import { networkTopCountries } from './top_countries';
+import { networkTopNFlow } from './top_n_flow';
import { networkUsers } from './users';
export const networkFactory: Record<
@@ -39,17 +36,11 @@ export const networkFactory: Record<
[NetworkQueries.overview]: networkOverview,
[NetworkQueries.tls]: networkTls,
[NetworkQueries.topCountries]: networkTopCountries,
- [NetworkQueries.topCountriesEntities]: networkTopCountriesEntities,
[NetworkQueries.topNFlow]: networkTopNFlow,
- [NetworkQueries.topNFlowEntities]: networkTopNFlowEntities,
[NetworkQueries.users]: networkUsers,
[NetworkKpiQueries.dns]: networkKpiDns,
- [NetworkKpiQueries.dnsEntities]: networkKpiDnsEntities,
[NetworkKpiQueries.networkEvents]: networkKpiNetworkEvents,
- [NetworkKpiQueries.networkEventsEntities]: networkKpiNetworkEventsEntities,
[NetworkKpiQueries.tlsHandshakes]: networkKpiTlsHandshakes,
- [NetworkKpiQueries.tlsHandshakesEntities]: networkKpiTlsHandshakesEntities,
[NetworkKpiQueries.uniqueFlows]: networkKpiUniqueFlows,
[NetworkKpiQueries.uniquePrivateIps]: networkKpiUniquePrivateIps,
- [NetworkKpiQueries.uniquePrivateIpsEntities]: networkKpiUniquePrivateIpsEntities,
};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/index.ts
index b8a21d4791c57..25dd078955203 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/index.ts
@@ -13,7 +13,6 @@ import {
} from '../../../../../../../common/search_strategy/security_solution/network';
import { inspectStringifyObject } from '../../../../../../utils/build_query';
import { SecuritySolutionFactory } from '../../../types';
-import { buildDnsQueryEntities } from './query.network_kip_dns_entities.dsl';
import { buildDnsQuery } from './query.network_kpi_dns.dsl';
export const networkKpiDns: SecuritySolutionFactory = {
@@ -34,21 +33,3 @@ export const networkKpiDns: SecuritySolutionFactory = {
};
},
};
-
-export const networkKpiDnsEntities: SecuritySolutionFactory = {
- buildDsl: (options: NetworkKpiDnsRequestOptions) => buildDnsQueryEntities(options),
- parse: async (
- options: NetworkKpiDnsRequestOptions,
- response: IEsSearchResponse
- ): Promise => {
- const inspect = {
- dsl: [inspectStringifyObject(buildDnsQueryEntities(options))],
- };
- return {
- ...response,
- inspect,
- // @ts-expect-error code doesn't handle TotalHits
- dnsQueries: response.rawResponse.aggregations?.dns?.value ?? null,
- };
- },
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/query.network_kip_dns_entities.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/query.network_kip_dns_entities.dsl.ts
deleted file mode 100644
index c0317772e5fa9..0000000000000
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/query.network_kip_dns_entities.dsl.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { NetworkKpiDnsRequestOptions } from '../../../../../../../common/search_strategy/security_solution/network';
-import { createQueryFilterClauses } from '../../../../../../utils/build_query';
-
-export const buildDnsQueryEntities = ({
- filterQuery,
- timerange: { from, to },
- defaultIndex,
-}: NetworkKpiDnsRequestOptions) => {
- const filter = [
- ...createQueryFilterClauses(filterQuery),
- {
- range: {
- '@timestamp': {
- gte: from,
- lte: to,
- format: 'strict_date_optional_time',
- },
- },
- },
- ];
-
- const dslQuery = {
- index: defaultIndex,
- allow_no_indices: true,
- ignore_unavailable: true,
- track_total_hits: false,
- body: {
- aggs: {
- dns: {
- sum: {
- field: 'metrics.dns.queries.value_count',
- },
- },
- },
- query: {
- bool: {
- filter,
- },
- },
- size: 0,
- },
- };
-
- return dslQuery;
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/index.ts
index 326d4f33e7a93..2a18bf3b5de86 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/index.ts
@@ -11,26 +11,19 @@ import {
} from '../../../../../../common/search_strategy/security_solution';
import { SecuritySolutionFactory } from '../../types';
-import { networkKpiDns, networkKpiDnsEntities } from './dns';
-import { networkKpiNetworkEvents, networkKpiNetworkEventsEntities } from './network_events';
-import { networkKpiTlsHandshakes, networkKpiTlsHandshakesEntities } from './tls_handshakes';
+import { networkKpiDns } from './dns';
+import { networkKpiNetworkEvents } from './network_events';
+import { networkKpiTlsHandshakes } from './tls_handshakes';
import { networkKpiUniqueFlows } from './unique_flows';
-import {
- networkKpiUniquePrivateIps,
- networkKpiUniquePrivateIpsEntities,
-} from './unique_private_ips';
+import { networkKpiUniquePrivateIps } from './unique_private_ips';
export const networkKpiFactory: Record<
NetworkKpiQueries,
SecuritySolutionFactory
> = {
[NetworkKpiQueries.dns]: networkKpiDns,
- [NetworkKpiQueries.dnsEntities]: networkKpiDnsEntities,
[NetworkKpiQueries.networkEvents]: networkKpiNetworkEvents,
- [NetworkKpiQueries.networkEventsEntities]: networkKpiNetworkEventsEntities,
[NetworkKpiQueries.tlsHandshakes]: networkKpiTlsHandshakes,
- [NetworkKpiQueries.tlsHandshakesEntities]: networkKpiTlsHandshakesEntities,
[NetworkKpiQueries.uniqueFlows]: networkKpiUniqueFlows,
[NetworkKpiQueries.uniquePrivateIps]: networkKpiUniquePrivateIps,
- [NetworkKpiQueries.uniquePrivateIpsEntities]: networkKpiUniquePrivateIpsEntities,
};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/index.ts
index ac3d01512428a..89773581f6515 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/index.ts
@@ -14,7 +14,6 @@ import {
import { inspectStringifyObject } from '../../../../../../utils/build_query';
import { SecuritySolutionFactory } from '../../../types';
import { buildNetworkEventsQuery } from './query.network_kpi_network_events.dsl';
-import { buildNetworkEventsQueryEntities } from './query.network_kpi_network_events_entities.dsl';
export const networkKpiNetworkEvents: SecuritySolutionFactory = {
buildDsl: (options: NetworkKpiNetworkEventsRequestOptions) => buildNetworkEventsQuery(options),
@@ -34,24 +33,3 @@ export const networkKpiNetworkEvents: SecuritySolutionFactory =
- {
- buildDsl: (options: NetworkKpiNetworkEventsRequestOptions) =>
- buildNetworkEventsQueryEntities(options),
- parse: async (
- options: NetworkKpiNetworkEventsRequestOptions,
- response: IEsSearchResponse
- ): Promise => {
- const inspect = {
- dsl: [inspectStringifyObject(buildNetworkEventsQueryEntities(options))],
- };
-
- return {
- ...response,
- inspect,
- // @ts-expect-error code doesn't handle TotalHits
- networkEvents: response.rawResponse.aggregations?.events?.value ?? null,
- };
- },
- };
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/query.network_kpi_network_events_entities.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/query.network_kpi_network_events_entities.dsl.ts
deleted file mode 100644
index bb40da0a064fb..0000000000000
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/query.network_kpi_network_events_entities.dsl.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { NetworkKpiNetworkEventsRequestOptions } from '../../../../../../../common/search_strategy/security_solution/network';
-import { createQueryFilterClauses } from '../../../../../../utils/build_query';
-
-export const buildNetworkEventsQueryEntities = ({
- filterQuery,
- timerange: { from, to },
- defaultIndex,
-}: NetworkKpiNetworkEventsRequestOptions) => {
- const filter = [
- ...createQueryFilterClauses(filterQuery),
- {
- range: {
- '@timestamp': {
- gte: from,
- lte: to,
- format: 'strict_date_optional_time',
- },
- },
- },
- ];
-
- const dslQuery = {
- index: defaultIndex,
- allow_no_indices: true,
- ignore_unavailable: true,
- track_total_hits: false,
- body: {
- aggs: {
- events: {
- sum: {
- field: 'metrics.network.events.value_count',
- },
- },
- },
- query: {
- bool: {
- filter,
- },
- },
- size: 0,
- },
- };
-
- return dslQuery;
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/index.ts
index cb57d63f4f3a6..1f3c7280cd7c1 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/index.ts
@@ -14,7 +14,6 @@ import {
import { inspectStringifyObject } from '../../../../../../utils/build_query';
import { SecuritySolutionFactory } from '../../../types';
import { buildTlsHandshakeQuery } from './query.network_kpi_tls_handshakes.dsl';
-import { buildTlsHandshakeQueryEntities } from './query.network_kpi_tls_handshakes_entities.dsl';
export const networkKpiTlsHandshakes: SecuritySolutionFactory = {
buildDsl: (options: NetworkKpiTlsHandshakesRequestOptions) => buildTlsHandshakeQuery(options),
@@ -34,24 +33,3 @@ export const networkKpiTlsHandshakes: SecuritySolutionFactory =
- {
- buildDsl: (options: NetworkKpiTlsHandshakesRequestOptions) =>
- buildTlsHandshakeQueryEntities(options),
- parse: async (
- options: NetworkKpiTlsHandshakesRequestOptions,
- response: IEsSearchResponse
- ): Promise => {
- const inspect = {
- dsl: [inspectStringifyObject(buildTlsHandshakeQueryEntities(options))],
- };
-
- return {
- ...response,
- inspect,
- // @ts-expect-error code doesn't handle TotalHits
- tlsHandshakes: response.rawResponse.aggregations?.tls?.value ?? null,
- };
- },
- };
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/query.network_kpi_tls_handshakes_entities.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/query.network_kpi_tls_handshakes_entities.dsl.ts
deleted file mode 100644
index bd7a464e1a090..0000000000000
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/query.network_kpi_tls_handshakes_entities.dsl.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { NetworkKpiTlsHandshakesRequestOptions } from '../../../../../../../common/search_strategy/security_solution/network';
-import { createQueryFilterClauses } from '../../../../../../utils/build_query';
-
-export const buildTlsHandshakeQueryEntities = ({
- filterQuery,
- timerange: { from, to },
- defaultIndex,
-}: NetworkKpiTlsHandshakesRequestOptions) => {
- const filter = [
- ...createQueryFilterClauses(filterQuery),
- {
- range: {
- '@timestamp': {
- gte: from,
- lte: to,
- format: 'strict_date_optional_time',
- },
- },
- },
- ];
-
- const dslQuery = {
- index: defaultIndex,
- allow_no_indices: true,
- ignore_unavailable: true,
- track_total_hits: false,
- body: {
- aggs: {
- tls: {
- sum: {
- field: 'metrics.network.tls.version.value_count',
- },
- },
- },
- query: {
- bool: {
- filter,
- },
- },
- size: 0,
- },
- };
-
- return dslQuery;
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/index.ts
index 927e2a2fb5aee..9fa63eb939977 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/index.ts
@@ -17,7 +17,6 @@ import { inspectStringifyObject } from '../../../../../../utils/build_query';
import { SecuritySolutionFactory } from '../../../types';
import { formatHistogramData } from '../common';
import { buildUniquePrivateIpsQuery } from './query.network_kpi_unique_private_ips.dsl';
-import { buildUniquePrivateIpsQueryEntities } from './query.network_kpi_unique_private_ips_entities.dsl';
export const networkKpiUniquePrivateIps: SecuritySolutionFactory =
{
@@ -63,48 +62,3 @@ export const networkKpiUniquePrivateIps: SecuritySolutionFactory =
- {
- // @ts-expect-error auto_date_histogram.buckets is incompatible
- buildDsl: (options: NetworkKpiUniquePrivateIpsRequestOptions) =>
- buildUniquePrivateIpsQueryEntities(options),
- parse: async (
- options: NetworkKpiUniquePrivateIpsRequestOptions,
- response: IEsSearchResponse
- ): Promise => {
- const inspect = {
- dsl: [inspectStringifyObject(buildUniquePrivateIpsQueryEntities(options))],
- };
-
- const uniqueSourcePrivateIpsHistogram = getOr(
- null,
- 'aggregations.source.histogram.buckets',
- response.rawResponse
- );
- const uniqueDestinationPrivateIpsHistogram = getOr(
- null,
- 'aggregations.destination.histogram.buckets',
- response.rawResponse
- );
-
- return {
- ...response,
- inspect,
- uniqueSourcePrivateIps: getOr(
- null,
- 'aggregations.source.unique_private_ips.value',
- response.rawResponse
- ),
- uniqueDestinationPrivateIps: getOr(
- null,
- 'aggregations.destination.unique_private_ips.value',
- response.rawResponse
- ),
- uniqueSourcePrivateIpsHistogram: formatHistogramData(uniqueSourcePrivateIpsHistogram),
- uniqueDestinationPrivateIpsHistogram: formatHistogramData(
- uniqueDestinationPrivateIpsHistogram
- ),
- };
- },
- };
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/query.network_kpi_unique_private_ips_entities.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/query.network_kpi_unique_private_ips_entities.dsl.ts
deleted file mode 100644
index 922a082439807..0000000000000
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/query.network_kpi_unique_private_ips_entities.dsl.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import {
- NetworkKpiUniquePrivateIpsRequestOptions,
- UniquePrivateAttributeQuery,
-} from '../../../../../../../common/search_strategy/security_solution/network';
-import { createQueryFilterClauses } from '../../../../../../utils/build_query';
-
-const getUniquePrivateIpsFilter = (attrQuery: UniquePrivateAttributeQuery) => ({
- bool: {
- should: [
- {
- term: {
- [`${attrQuery}.ip`]: '10.0.0.0/8',
- },
- },
- {
- term: {
- [`${attrQuery}.ip`]: '192.168.0.0/16',
- },
- },
- {
- term: {
- [`${attrQuery}.ip`]: '172.16.0.0/12',
- },
- },
- {
- term: {
- [`${attrQuery}.ip`]: 'fd00::/8',
- },
- },
- ],
- minimum_should_match: 1,
- },
-});
-
-const getAggs = (attrQuery: 'source' | 'destination') => ({
- [attrQuery]: {
- filter: getUniquePrivateIpsFilter(attrQuery),
- aggs: {
- unique_private_ips: {
- cardinality: {
- field: `${attrQuery}.ip`,
- },
- },
- histogram: {
- auto_date_histogram: {
- field: '@timestamp',
- buckets: '6',
- },
- aggs: {
- count: {
- cardinality: {
- field: `${attrQuery}.ip`,
- },
- },
- },
- },
- },
- },
-});
-
-export const buildUniquePrivateIpsQueryEntities = ({
- filterQuery,
- timerange: { from, to },
- defaultIndex,
-}: NetworkKpiUniquePrivateIpsRequestOptions) => {
- const filter = [
- ...createQueryFilterClauses(filterQuery),
- {
- range: {
- '@timestamp': {
- gte: from,
- lte: to,
- format: 'strict_date_optional_time',
- },
- },
- },
- ];
-
- const dslQuery = {
- allow_no_indices: true,
- index: defaultIndex,
- ignore_unavailable: true,
- track_total_hits: false,
- body: {
- aggregations: {
- ...getAggs('source'),
- ...getAggs('destination'),
- },
- query: {
- bool: {
- filter,
- },
- },
- size: 0,
- },
- };
-
- return dslQuery;
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.ts
index e65ff6e4d1ad7..ef114dcb6167d 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.ts
@@ -22,7 +22,6 @@ import { SecuritySolutionFactory } from '../../types';
import { getTopCountriesEdges } from './helpers';
import { buildTopCountriesQuery } from './query.top_countries_network.dsl';
-import { buildTopCountriesQueryEntities } from './query.top_countries_network_entities.dsl';
export const networkTopCountries: SecuritySolutionFactory = {
buildDsl: (options: NetworkTopCountriesRequestOptions) => {
@@ -61,41 +60,3 @@ export const networkTopCountries: SecuritySolutionFactory = {
- buildDsl: (options: NetworkTopCountriesRequestOptions) => {
- if (options.pagination && options.pagination.querySize >= DEFAULT_MAX_TABLE_QUERY_SIZE) {
- throw new Error(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`);
- }
- return buildTopCountriesQueryEntities(options);
- },
- parse: async (
- options: NetworkTopCountriesRequestOptions,
- response: IEsSearchResponse
- ): Promise => {
- const { activePage, cursorStart, fakePossibleCount, querySize } = options.pagination;
- const totalCount = getOr(0, 'aggregations.top_countries_count.value', response.rawResponse);
- const networkTopCountriesEdges: NetworkTopCountriesEdges[] = getTopCountriesEdges(
- response,
- options
- );
- const fakeTotalCount = fakePossibleCount <= totalCount ? fakePossibleCount : totalCount;
- const edges = networkTopCountriesEdges.splice(cursorStart, querySize - cursorStart);
- const inspect = {
- dsl: [inspectStringifyObject(buildTopCountriesQueryEntities(options))],
- };
- const showMorePagesIndicator = totalCount > fakeTotalCount;
-
- return {
- ...response,
- edges,
- inspect,
- pageInfo: {
- activePage: activePage ?? 0,
- fakeTotalCount,
- showMorePagesIndicator,
- },
- totalCount,
- };
- },
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/query.top_countries_network_entities.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/query.top_countries_network_entities.dsl.ts
deleted file mode 100644
index 7f1d27db45d2d..0000000000000
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/query.top_countries_network_entities.dsl.ts
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { createQueryFilterClauses } from '../../../../../utils/build_query';
-import { assertUnreachable } from '../../../../../../common/utility_types';
-import {
- Direction,
- FlowTargetSourceDest,
- NetworkTopTablesFields,
- NetworkTopCountriesRequestOptions,
- SortField,
-} from '../../../../../../common/search_strategy';
-
-// TODO: This is the same as the other one, so move this into helpers.
-const getCountAgg = (flowTarget: FlowTargetSourceDest) => ({
- top_countries_count: {
- cardinality: {
- field: `${flowTarget}.geo.country_iso_code`,
- },
- },
-});
-
-export const buildTopCountriesQueryEntities = ({
- defaultIndex,
- filterQuery,
- flowTarget,
- sort,
- pagination: { querySize },
- timerange: { from, to },
- ip,
-}: NetworkTopCountriesRequestOptions) => {
- const filter = [
- ...createQueryFilterClauses(filterQuery),
- {
- range: {
- '@timestamp': {
- gte: from,
- lte: to,
- format: 'strict_date_optional_time',
- },
- },
- },
- ];
-
- const dslQuery = {
- allow_no_indices: true,
- index: defaultIndex,
- ignore_unavailable: true,
- body: {
- aggregations: {
- ...getCountAgg(flowTarget),
- ...getFlowTargetAggs(sort, flowTarget, querySize),
- },
- query: {
- bool: ip
- ? {
- filter,
- should: [
- {
- term: {
- [`${getOppositeField(flowTarget)}.ip`]: ip,
- },
- },
- ],
- minimum_should_match: 1,
- }
- : {
- filter,
- },
- },
- },
- size: 0,
- track_total_hits: false,
- };
- return dslQuery;
-};
-
-const getFlowTargetAggs = (
- sort: SortField,
- flowTarget: FlowTargetSourceDest,
- querySize: number
-) => ({
- [flowTarget]: {
- terms: {
- field: `${flowTarget}.geo.country_iso_code`,
- size: querySize,
- order: {
- ...getQueryOrder(sort),
- },
- },
- aggs: {
- bytes_in: {
- sum: {
- field: `metrics.${getOppositeField(flowTarget)}.bytes.sum`,
- },
- },
- bytes_out: {
- sum: {
- field: `metrics.${flowTarget}.bytes.sum`,
- },
- },
- flows: {
- // TODO: Should we use max here and/or do a hybrid with a max here for performance?
- avg: {
- field: 'metrics.network.community_id.cardinality',
- },
- },
- source_ips: {
- avg: {
- field: 'metrics.source.ip.cardinality',
- },
- },
- destination_ips: {
- avg: {
- field: 'metrics.destination.ip.cardinality',
- },
- },
- },
- },
-});
-
-// TODO: This is the same as the other one, so move this to helpers and use it from there.
-export const getOppositeField = (flowTarget: FlowTargetSourceDest): FlowTargetSourceDest => {
- switch (flowTarget) {
- case FlowTargetSourceDest.source:
- return FlowTargetSourceDest.destination;
- case FlowTargetSourceDest.destination:
- return FlowTargetSourceDest.source;
- }
- assertUnreachable(flowTarget);
-};
-
-// TODO: This is the same as the other one, so move this to helpers and use it from there.
-type QueryOrder =
- | { bytes_in: Direction }
- | { bytes_out: Direction }
- | { flows: Direction }
- | { destination_ips: Direction }
- | { source_ips: Direction };
-
-// TODO: This is the same as the other one, so move this to helpers and use it from there.
-const getQueryOrder = (
- networkTopCountriesSortField: SortField
-): QueryOrder => {
- switch (networkTopCountriesSortField.field) {
- case NetworkTopTablesFields.bytes_in:
- return { bytes_in: networkTopCountriesSortField.direction };
- case NetworkTopTablesFields.bytes_out:
- return { bytes_out: networkTopCountriesSortField.direction };
- case NetworkTopTablesFields.flows:
- return { flows: networkTopCountriesSortField.direction };
- case NetworkTopTablesFields.destination_ips:
- return { destination_ips: networkTopCountriesSortField.direction };
- case NetworkTopTablesFields.source_ips:
- return { source_ips: networkTopCountriesSortField.direction };
- }
- assertUnreachable(networkTopCountriesSortField.field);
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/index.ts
index 06fac027685bd..218c9361517ce 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/index.ts
@@ -22,7 +22,6 @@ import { SecuritySolutionFactory } from '../../types';
import { getTopNFlowEdges } from './helpers';
import { buildTopNFlowQuery } from './query.top_n_flow_network.dsl';
-import { buildTopNFlowQueryEntities } from './query.top_n_flow_network_entities.dsl';
export const networkTopNFlow: SecuritySolutionFactory = {
buildDsl: (options: NetworkTopNFlowRequestOptions) => {
@@ -58,38 +57,3 @@ export const networkTopNFlow: SecuritySolutionFactory =
};
},
};
-
-export const networkTopNFlowEntities: SecuritySolutionFactory = {
- buildDsl: (options: NetworkTopNFlowRequestOptions) => {
- if (options.pagination && options.pagination.querySize >= DEFAULT_MAX_TABLE_QUERY_SIZE) {
- throw new Error(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`);
- }
- return buildTopNFlowQueryEntities(options);
- },
- parse: async (
- options: NetworkTopNFlowRequestOptions,
- response: IEsSearchResponse
- ): Promise => {
- const { activePage, cursorStart, fakePossibleCount, querySize } = options.pagination;
- const totalCount = getOr(0, 'aggregations.top_n_flow_count.value', response.rawResponse);
- const networkTopNFlowEdges: NetworkTopNFlowEdges[] = getTopNFlowEdges(response, options);
- const fakeTotalCount = fakePossibleCount <= totalCount ? fakePossibleCount : totalCount;
- const edges = networkTopNFlowEdges.splice(cursorStart, querySize - cursorStart);
- const inspect = {
- dsl: [inspectStringifyObject(buildTopNFlowQueryEntities(options))],
- };
- const showMorePagesIndicator = totalCount > fakeTotalCount;
-
- return {
- ...response,
- edges,
- inspect,
- pageInfo: {
- activePage: activePage ?? 0,
- fakeTotalCount,
- showMorePagesIndicator,
- },
- totalCount,
- };
- },
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/query.top_n_flow_network_entities.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/query.top_n_flow_network_entities.dsl.ts
deleted file mode 100644
index d11a2debf3cff..0000000000000
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/query.top_n_flow_network_entities.dsl.ts
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import {
- SortField,
- FlowTargetSourceDest,
- NetworkTopTablesFields,
- NetworkTopNFlowRequestOptions,
-} from '../../../../../../common/search_strategy';
-import { createQueryFilterClauses } from '../../../../../utils/build_query';
-import { getOppositeField } from '../helpers';
-import { getQueryOrder } from './helpers';
-
-// TODO: This is the same as the other one, so move this into helpers.
-const getCountAgg = (flowTarget: FlowTargetSourceDest) => ({
- top_n_flow_count: {
- cardinality: {
- field: `${flowTarget}.ip`,
- },
- },
-});
-
-export const buildTopNFlowQueryEntities = ({
- defaultIndex,
- filterQuery,
- flowTarget,
- sort,
- pagination: { querySize },
- timerange: { from, to },
- ip,
-}: NetworkTopNFlowRequestOptions) => {
- const filter = [
- ...createQueryFilterClauses(filterQuery),
- {
- range: {
- '@timestamp': {
- gte: from,
- lte: to,
- format: 'strict_date_optional_time',
- },
- },
- },
- ];
-
- const dslQuery = {
- allow_no_indices: true,
- index: defaultIndex,
- ignore_unavailable: true,
- body: {
- aggregations: {
- ...getCountAgg(flowTarget),
- ...getFlowTargetAggs(sort, flowTarget, querySize),
- },
- query: {
- bool: ip
- ? {
- filter,
- should: [
- {
- term: {
- [`${getOppositeField(flowTarget)}.ip`]: ip,
- },
- },
- ],
- minimum_should_match: 1,
- }
- : {
- filter,
- },
- },
- },
- size: 0,
- track_total_hits: false,
- };
- return dslQuery;
-};
-
-const getFlowTargetAggs = (
- sort: SortField,
- flowTarget: FlowTargetSourceDest,
- querySize: number
-) => ({
- [flowTarget]: {
- terms: {
- field: `${flowTarget}.ip`,
- size: querySize,
- order: {
- ...getQueryOrder(sort),
- },
- },
- aggs: {
- bytes_in: {
- sum: {
- field: `metrics.${getOppositeField(flowTarget)}.bytes.sum`,
- },
- },
- bytes_out: {
- sum: {
- field: `metrics.${flowTarget}.bytes.sum`,
- },
- },
- domain: {
- terms: {
- field: `${flowTarget}.domain`,
- order: {
- timestamp: 'desc',
- },
- },
- aggs: {
- timestamp: {
- max: {
- field: '@timestamp',
- },
- },
- },
- },
- location: {
- filter: {
- exists: {
- field: `${flowTarget}.geo`,
- },
- },
- aggs: {
- top_geo: {
- top_hits: {
- _source: `${flowTarget}.geo.*`,
- size: 1,
- },
- },
- },
- },
- autonomous_system: {
- filter: {
- exists: {
- field: `${flowTarget}.as`,
- },
- },
- aggs: {
- top_as: {
- top_hits: {
- _source: `${flowTarget}.as.*`,
- size: 1,
- },
- },
- },
- },
- flows: {
- avg: {
- // TODO: Should we use a max here along with a hybrid query?
- field: 'metrics.network.community_id.cardinality',
- },
- },
- [`${getOppositeField(flowTarget)}_ips`]: {
- avg: {
- // TODO: Should we use a max here along with a hybrid query?
- field: `metrics.${getOppositeField(flowTarget)}.ip.cardinality`,
- },
- },
- },
- },
-});
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/dsl/query_entities.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/dsl/query_entities.dsl.ts
deleted file mode 100644
index 7c9c29a1efdc4..0000000000000
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/dsl/query_entities.dsl.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { isEmpty } from 'lodash/fp';
-import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
-
-import { createQueryFilterClauses } from '../../../../../../utils/build_query';
-import { UserAuthenticationsRequestOptions } from '../../../../../../../common/search_strategy';
-
-export const buildQueryEntities = ({
- filterQuery,
- timerange: { from, to },
- pagination: { querySize },
- defaultIndex,
- docValueFields,
- stackByField,
-}: UserAuthenticationsRequestOptions) => {
- const filter = [
- ...createQueryFilterClauses(filterQuery),
- {
- range: {
- '@timestamp': {
- gte: from,
- lte: to,
- format: 'strict_date_optional_time',
- },
- },
- },
- ];
-
- const dslQuery = {
- allow_no_indices: true,
- index: defaultIndex,
- ignore_unavailable: true,
- body: {
- ...(!isEmpty(docValueFields) ? { docvalue_fields: docValueFields } : {}),
- aggregations: {
- stack_by_count: {
- cardinality: {
- field: stackByField,
- },
- },
- stack_by: {
- terms: {
- size: querySize,
- field: stackByField,
- order: [
- { successes: 'desc' },
- { failures: 'desc' },
- ] as estypes.AggregationsTermsAggregationOrder,
- },
- aggs: {
- failures: {
- sum: {
- field: 'metrics.event.authentication.failure.value_count',
- },
- },
- successes: {
- sum: {
- field: 'metrics.event.authentication.success.value_count',
- },
- },
- },
- },
- },
- query: {
- bool: {
- filter,
- },
- },
- size: 0,
- },
- track_total_hits: false,
- };
-
- return dslQuery;
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/helpers.ts
index 02a89dd08a222..43baa4aadea14 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/helpers.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/helpers.ts
@@ -95,68 +95,3 @@ export const getHits = (response: StrategyResponseT
successes: bucket.successes.doc_count,
})
);
-
-export const getHitsEntities = (response: StrategyResponseType) =>
- getOr([], 'aggregations.stack_by.buckets', response.rawResponse).map(
- (bucket: AuthenticationBucket) => ({
- _id: getOr(
- `${bucket.key}+${bucket.doc_count}`,
- 'failures.lastFailure.hits.hits[0].id',
- bucket
- ),
- _source: {
- lastSuccess: getOr(null, 'successes.lastSuccess.hits.hits[0]._source', bucket),
- lastFailure: getOr(null, 'failures.lastFailure.hits.hits[0]._source', bucket),
- },
- stackedValue: bucket.key,
- failures: bucket.failures.value,
- successes: bucket.successes.value,
- })
- );
-
-export const formatAuthenticationEntitiesData = (
- fields: readonly string[] = authenticationsFields,
- hit: AuthenticationHit,
- fieldMap: Readonly>
-): AuthenticationsEdges => {
- return fields.reduce(
- (flattenedFields, fieldName) => {
- if (hit.cursor) {
- flattenedFields.cursor.value = hit.cursor;
- }
- flattenedFields.node = {
- ...flattenedFields.node,
- ...{
- _id: hit._id,
- stackedValue: [hit.stackedValue],
- failures: hit.failures,
- successes: hit.successes,
- },
- };
- const mergedResult = mergeFieldsWithHit(fieldName, flattenedFields, fieldMap, hit);
- const fieldPath = `node.${fieldName}`;
- const fieldValue = get(fieldPath, mergedResult);
- if (!isEmpty(fieldValue)) {
- return set(
- fieldPath,
- toObjectArrayOfStrings(fieldValue).map(({ str }) => str),
- mergedResult
- );
- } else {
- return mergedResult;
- }
- },
- {
- node: {
- failures: 0,
- successes: 0,
- _id: '',
- stackedValue: [''],
- },
- cursor: {
- value: '',
- tiebreaker: null,
- },
- }
- );
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/index.tsx b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/index.tsx
index 11400166e3344..e748023bfe76c 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/index.tsx
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/index.tsx
@@ -22,15 +22,7 @@ import { inspectStringifyObject } from '../../../../../utils/build_query';
import { SecuritySolutionFactory } from '../../types';
import { auditdFieldsMap, buildQuery as buildAuthenticationQuery } from './dsl/query.dsl';
-import { buildQueryEntities as buildAuthenticationQueryEntities } from './dsl/query_entities.dsl';
-
-import {
- authenticationsFields,
- formatAuthenticationData,
- formatAuthenticationEntitiesData,
- getHits,
- getHitsEntities,
-} from './helpers';
+import { authenticationsFields, formatAuthenticationData, getHits } from './helpers';
export const authentications: SecuritySolutionFactory = {
buildDsl: (options: UserAuthenticationsRequestOptions) => {
@@ -71,44 +63,3 @@ export const authentications: SecuritySolutionFactory = {
- buildDsl: (options: UserAuthenticationsRequestOptions) => {
- if (options.pagination && options.pagination.querySize >= DEFAULT_MAX_TABLE_QUERY_SIZE) {
- throw new Error(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`);
- }
-
- return buildAuthenticationQueryEntities(options);
- },
- parse: async (
- options: UserAuthenticationsRequestOptions,
- response: IEsSearchResponse
- ): Promise => {
- const { activePage, cursorStart, fakePossibleCount, querySize } = options.pagination;
- const totalCount = getOr(0, 'aggregations.stack_by_count.value', response.rawResponse);
-
- const fakeTotalCount = fakePossibleCount <= totalCount ? fakePossibleCount : totalCount;
- const hits: AuthenticationHit[] = getHitsEntities(response);
- const authenticationEdges: AuthenticationsEdges[] = hits.map((hit) =>
- formatAuthenticationEntitiesData(authenticationsFields, hit, auditdFieldsMap)
- );
-
- const edges = authenticationEdges.splice(cursorStart, querySize - cursorStart);
- const inspect = {
- dsl: [inspectStringifyObject(buildAuthenticationQueryEntities(options))],
- };
- const showMorePagesIndicator = totalCount > fakeTotalCount;
-
- return {
- ...response,
- inspect,
- edges,
- totalCount,
- pageInfo: {
- activePage: activePage ?? 0,
- fakeTotalCount,
- showMorePagesIndicator,
- },
- };
- },
-};
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/index.ts
index 0b13319cc11c7..0720244a73ff3 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/index.ts
@@ -10,7 +10,7 @@ import { UsersQueries } from '../../../../../common/search_strategy/security_sol
import { SecuritySolutionFactory } from '../types';
import { allUsers } from './all';
-import { authentications, authenticationsEntities } from './authentications';
+import { authentications } from './authentications';
import { userDetails } from './details';
import { totalUsersKpi } from './kpi/total_users';
@@ -19,5 +19,4 @@ export const usersFactory: Record>;
@@ -232,26 +229,6 @@ export const initUiSettings = (
requiresPageReload: false,
schema: schema.boolean(),
},
- // TODO: Remove this check once the experimental flag is removed
- ...(experimentalFeatures.metricsEntitiesEnabled
- ? {
- [DEFAULT_TRANSFORMS]: {
- name: i18n.translate('xpack.securitySolution.uiSettings.transforms', {
- defaultMessage: 'Default transforms to use',
- }),
- value: DEFAULT_TRANSFORMS_SETTING,
- type: 'json',
- description: i18n.translate('xpack.securitySolution.uiSettings.transformDescription', {
- // TODO: Add a hyperlink to documentation about this feature
- defaultMessage: 'Experimental: Enable an application cache through transforms',
- }),
- sensitive: true,
- category: [APP_ID],
- requiresPageReload: false,
- schema: transformConfigSchema,
- },
- }
- : {}),
};
uiSettings.register(orderSettings(securityUiSettings));
diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json
index 175879805b251..a1abc744c3336 100644
--- a/x-pack/plugins/translations/translations/fr-FR.json
+++ b/x-pack/plugins/translations/translations/fr-FR.json
@@ -19873,7 +19873,6 @@
"xpack.securitySolution.containers.detectionEngine.rulesAndTimelines": "Impossible de récupérer les règles et les chronologies",
"xpack.securitySolution.containers.detectionEngine.tagFetchFailDescription": "Impossible de récupérer les balises",
"xpack.securitySolution.containers.errors.stopJobFailureTitle": "Échec d'arrêt de la tâche",
- "xpack.securitySolution.containers.transforms.errorCreatingTransformsLabel": "Impossible de créer des transformations",
"xpack.securitySolution.customizeEventRenderers.customizeEventRenderersDescription": "Les outils de rendu d'événement transmettent automatiquement les détails les plus pertinents d'un événement pour révéler son histoire",
"xpack.securitySolution.customizeEventRenderers.customizeEventRenderersTitle": "Personnaliser les outils de rendu d'événement",
"xpack.securitySolution.customizeEventRenderers.disableAllRenderersButtonLabel": "Tout désactiver",
@@ -22307,8 +22306,6 @@
"xpack.securitySolution.uiSettings.newsFeedUrlDescription": "Le contenu du fil d'actualités sera récupéré à partir de cette URL
",
"xpack.securitySolution.uiSettings.rulesTableRefresh": "Actualisation automatique des règles",
"xpack.securitySolution.uiSettings.rulesTableRefreshDescription": "Active l'actualisation automatique sur tous les tableaux de règles et de monitorings, en millisecondes
",
- "xpack.securitySolution.uiSettings.transformDescription": "Expérimental : active un cache d'application via les transformations",
- "xpack.securitySolution.uiSettings.transforms": "Transformations par défaut à utiliser",
"xpack.securitySolution.uncommonProcesses.errorSearchDescription": "Une erreur s'est produite sur une recherche de processus inhabituels",
"xpack.securitySolution.uncommonProcesses.failSearchDescription": "Impossible de lancer la recherche sur les processus inhabituels",
"xpack.securitySolution.uncommonProcessTable.hostsTitle": "Noms d'hôtes",
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index fd11b97f873a7..d58da0f2ed657 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -22697,7 +22697,6 @@
"xpack.securitySolution.containers.detectionEngine.rulesAndTimelines": "ルールとタイムラインを取得できませんでした",
"xpack.securitySolution.containers.detectionEngine.tagFetchFailDescription": "タグを取得できませんでした",
"xpack.securitySolution.containers.errors.stopJobFailureTitle": "ジョブ停止エラー",
- "xpack.securitySolution.containers.transforms.errorCreatingTransformsLabel": "変換を作成できませんでした",
"xpack.securitySolution.contextMenuItemByRouter.viewDetails": "詳細を表示",
"xpack.securitySolution.customizeEventRenderers.customizeEventRenderersDescription": "イベントレンダラーは、イベントで最も関連性が高い詳細情報を自動的に表示し、ストーリーを明らかにします",
"xpack.securitySolution.customizeEventRenderers.customizeEventRenderersTitle": "イベントレンダラーのカスタマイズ",
@@ -25497,8 +25496,6 @@
"xpack.securitySolution.uiSettings.newsFeedUrlDescription": "ニュースフィードコンテンツはこの URL から取得されます
",
"xpack.securitySolution.uiSettings.rulesTableRefresh": "ルール自動更新",
"xpack.securitySolution.uiSettings.rulesTableRefreshDescription": "すべてのルールと監視テーブルの自動更新を有効にします(ミリ秒)
",
- "xpack.securitySolution.uiSettings.transformDescription": "実験:変換を通してアプリケーションキャッシュを有効にする",
- "xpack.securitySolution.uiSettings.transforms": "使用するデフォルトの変換",
"xpack.securitySolution.uncommonProcesses.errorSearchDescription": "一般的ではないプロセス検索でエラーが発生しました",
"xpack.securitySolution.uncommonProcesses.failSearchDescription": "一般的ではないプロセスで検索を実行できませんでした",
"xpack.securitySolution.uncommonProcessTable.hostsTitle": "ホスト名",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index d3d6b3b18a8bd..1f8bcf7b4fb74 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -22724,7 +22724,6 @@
"xpack.securitySolution.containers.detectionEngine.rulesAndTimelines": "无法提取规则和时间线",
"xpack.securitySolution.containers.detectionEngine.tagFetchFailDescription": "无法提取标签",
"xpack.securitySolution.containers.errors.stopJobFailureTitle": "停止作业失败",
- "xpack.securitySolution.containers.transforms.errorCreatingTransformsLabel": "无法创建转换",
"xpack.securitySolution.contextMenuItemByRouter.viewDetails": "查看详情",
"xpack.securitySolution.customizeEventRenderers.customizeEventRenderersDescription": "事件呈现器自动在事件中传送最相关的详情,以揭示其故事",
"xpack.securitySolution.customizeEventRenderers.customizeEventRenderersTitle": "定制事件呈现器",
@@ -25526,8 +25525,6 @@
"xpack.securitySolution.uiSettings.newsFeedUrlDescription": "将从此 URL 检索新闻源内容
",
"xpack.securitySolution.uiSettings.rulesTableRefresh": "规则自动刷新",
"xpack.securitySolution.uiSettings.rulesTableRefreshDescription": "对所有规则和监测表启用自动刷新(毫秒)
",
- "xpack.securitySolution.uiSettings.transformDescription": "实验性:通过转换启用应用程序缓存",
- "xpack.securitySolution.uiSettings.transforms": "要使用的默认转换",
"xpack.securitySolution.uncommonProcesses.errorSearchDescription": "搜索不常见进程时发生错误",
"xpack.securitySolution.uncommonProcesses.failSearchDescription": "无法对不常见进程执行搜索",
"xpack.securitySolution.uncommonProcessTable.hostsTitle": "主机名",
diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json
index 752bf09d96df0..91b82bc785ae9 100644
--- a/x-pack/test/tsconfig.json
+++ b/x-pack/test/tsconfig.json
@@ -77,7 +77,6 @@
{ "path": "../plugins/licensing/tsconfig.json" },
{ "path": "../plugins/lists/tsconfig.json" },
{ "path": "../plugins/logstash/tsconfig.json" },
- { "path": "../plugins/metrics_entities/tsconfig.json" },
{ "path": "../plugins/ml/tsconfig.json" },
{ "path": "../plugins/monitoring/tsconfig.json" },
{ "path": "../plugins/observability/tsconfig.json" },
From 38d5202f558828bbc6b5320ae7fdf8677e563301 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Mon, 11 Apr 2022 14:03:07 -0600
Subject: [PATCH 22/75] [docs] fix table in Settings documentation (#129933)
* [docs] fix table in Settings documenation
* try passthrough
* triple pass through
* make code block
---
docs/setup/settings.asciidoc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc
index c8fa521f93947..f5dca28a7da1c 100644
--- a/docs/setup/settings.asciidoc
+++ b/docs/setup/settings.asciidoc
@@ -359,7 +359,7 @@ When `includeElasticMapsService` is turned off, only tile layer configured by <<
| Specifies the URL of a self hosted <>
| [[tilemap-settings]] `map.tilemap.options.attribution:` {ess-icon}
- | The map attribution string. Provide attributions in markdown and use '|' to delimit attributions, for example: `"[attribution 1](https://www.attribution1)|[attribution 2](https://www.attribution2)"`.
+ | The map attribution string. Provide attributions in markdown and use `\|` to delimit attributions, for example: `"[attribution 1](https://www.attribution1)\|[attribution 2](https://www.attribution2)"`.
*Default: `"© [Elastic Maps Service](https://www.elastic.co/elastic-maps-service)"`*
| [[tilemap-max-zoom]] `map.tilemap.options.maxZoom:` {ess-icon}
From 752385cc955d19b7102c60b62eee87ac0c0ab8a4 Mon Sep 17 00:00:00 2001
From: Christos Nasikas
Date: Mon, 11 Apr 2022 23:09:34 +0300
Subject: [PATCH 23/75] [Cases] Prevent pushing if the user does not have
permissions to connectors (#129843)
---
.../components/create/form_context.test.tsx | 26 +++++++++++++++++++
.../public/components/create/form_context.tsx | 2 +-
.../components/edit_connector/index.test.tsx | 15 +++++++++++
.../components/edit_connector/index.tsx | 4 +--
4 files changed, 44 insertions(+), 3 deletions(-)
diff --git a/x-pack/plugins/cases/public/components/create/form_context.test.tsx b/x-pack/plugins/cases/public/components/create/form_context.test.tsx
index 5e62415def154..1255131c17791 100644
--- a/x-pack/plugins/cases/public/components/create/form_context.test.tsx
+++ b/x-pack/plugins/cases/public/components/create/form_context.test.tsx
@@ -845,4 +845,30 @@ describe('Create case', () => {
pushCaseToExternalServiceOrder < onFormSubmitSuccessOrder
).toBe(true);
});
+
+ describe('Permissions', () => {
+ it('should not push to service if the user does not have access to actions', async () => {
+ mockedContext.coreStart.application.capabilities = {
+ ...mockedContext.coreStart.application.capabilities,
+ actions: { save: false, show: false },
+ };
+
+ const result = mockedContext.render(
+
+
+
+
+ );
+
+ await act(async () => {
+ fillFormReactTestingLib(result);
+ });
+
+ await act(async () => {
+ userEvent.click(result.getByTestId('create-case-submit'));
+ });
+
+ expect(pushCaseToExternalService).not.toHaveBeenCalled();
+ });
+ });
});
diff --git a/x-pack/plugins/cases/public/components/create/form_context.tsx b/x-pack/plugins/cases/public/components/create/form_context.tsx
index 3576ea8377731..8a89dfea3a811 100644
--- a/x-pack/plugins/cases/public/components/create/form_context.tsx
+++ b/x-pack/plugins/cases/public/components/create/form_context.tsx
@@ -93,7 +93,7 @@ export const FormContext: React.FC = ({
await afterCaseCreated(updatedCase, postComment);
}
- if (updatedCase?.id && dataConnectorId !== 'none') {
+ if (updatedCase?.id && connectorToUpdate.id !== 'none') {
await pushCaseToExternalService({
caseId: updatedCase.id,
connector: connectorToUpdate,
diff --git a/x-pack/plugins/cases/public/components/edit_connector/index.test.tsx b/x-pack/plugins/cases/public/components/edit_connector/index.test.tsx
index 040fe0866a84e..87d4ea8f1e586 100644
--- a/x-pack/plugins/cases/public/components/edit_connector/index.test.tsx
+++ b/x-pack/plugins/cases/public/components/edit_connector/index.test.tsx
@@ -361,4 +361,19 @@ describe('EditConnector ', () => {
expect(result.queryByTestId('has-data-to-push-button')).toBe(null);
});
});
+
+ it('does not show the edit connectors pencil if the user does not have read access to actions', async () => {
+ const defaultProps = getDefaultProps();
+ const props = { ...defaultProps, connectors: [] };
+ appMockRender.coreStart.application.capabilities = {
+ ...appMockRender.coreStart.application.capabilities,
+ actions: { save: false, show: false },
+ };
+
+ const result = appMockRender.render();
+ await waitFor(() => {
+ expect(result.getByTestId('connector-edit-header')).toBeInTheDocument();
+ expect(result.queryByTestId('connector-edit')).toBe(null);
+ });
+ });
});
diff --git a/x-pack/plugins/cases/public/components/edit_connector/index.tsx b/x-pack/plugins/cases/public/components/edit_connector/index.tsx
index 85bf7de10b7ca..3d87578e90d8f 100644
--- a/x-pack/plugins/cases/public/components/edit_connector/index.tsx
+++ b/x-pack/plugins/cases/public/components/edit_connector/index.tsx
@@ -288,11 +288,11 @@ export const EditConnector = React.memo(
justifyContent="spaceBetween"
responsive={false}
>
-
+
{i18n.CONNECTORS}
{isLoading && }
- {!isLoading && !editConnector && userCanCrud && (
+ {!isLoading && !editConnector && userCanCrud && actionsReadCapabilities && (
Date: Mon, 11 Apr 2022 21:37:15 +0100
Subject: [PATCH 24/75] [SecuritySolution] Remove additional Visualization
labels (#129920)
* remove metric labels
* remove metric labels
---
.../lens_attributes/network/kpi_dns_queries.ts | 2 +-
.../network/kpi_unique_private_ips_destination_metric.ts | 3 +--
.../network/kpi_unique_private_ips_source_metric.ts | 3 +--
3 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_dns_queries.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_dns_queries.ts
index 3b672c03d97f2..515ed379d8e4d 100644
--- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_dns_queries.ts
+++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_dns_queries.ts
@@ -69,7 +69,7 @@ export const kpiDnsQueriesLensAttributes: LensAttributes = {
'cea37c70-8f91-43bf-b9fe-72d8c049f6a3': {
columns: {
'0374e520-eae0-4ac1-bcfe-37565e7fc9e3': {
- label: 'DNS',
+ label: '',
dataType: 'number',
operationType: 'count',
isBucketed: false,
diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_destination_metric.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_destination_metric.ts
index b5664d8cb8348..20c509d376396 100644
--- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_destination_metric.ts
+++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_destination_metric.ts
@@ -5,7 +5,6 @@
* 2.0.
*/
-import { DESTINATION_CHART_LABEL } from '../../translations';
import { LensAttributes } from '../../types';
export const kpiUniquePrivateIpsDestinationMetricLensAttributes: LensAttributes = {
@@ -21,7 +20,7 @@ export const kpiUniquePrivateIpsDestinationMetricLensAttributes: LensAttributes
customLabel: true,
dataType: 'number',
isBucketed: false,
- label: DESTINATION_CHART_LABEL,
+ label: '',
operationType: 'unique_count',
scale: 'ratio',
sourceField: 'destination.ip',
diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_source_metric.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_source_metric.ts
index 4ddeacbe7fa4c..18fb960a0eb30 100644
--- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_source_metric.ts
+++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_source_metric.ts
@@ -4,7 +4,6 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { SOURCE_CHART_LABEL } from '../../translations';
import { LensAttributes } from '../../types';
export const kpiUniquePrivateIpsSourceMetricLensAttributes: LensAttributes = {
@@ -20,7 +19,7 @@ export const kpiUniquePrivateIpsSourceMetricLensAttributes: LensAttributes = {
customLabel: true,
dataType: 'number',
isBucketed: false,
- label: SOURCE_CHART_LABEL,
+ label: '',
operationType: 'unique_count',
scale: 'ratio',
sourceField: 'source.ip',
From 3c805d2bfc994b71bd78017a245a276fe0f140d4 Mon Sep 17 00:00:00 2001
From: Nicolas Chaulet
Date: Mon, 11 Apr 2022 17:03:53 -0400
Subject: [PATCH 25/75] [Fleet] Fix typo in logstash pipeline instructions
(#129939)
---
.../settings/components/logstash_instructions/helpers.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/logstash_instructions/helpers.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/logstash_instructions/helpers.tsx
index e6326eeb1ecc2..1239233b4e12d 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/logstash_instructions/helpers.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/logstash_instructions/helpers.tsx
@@ -16,7 +16,7 @@ export function getLogstashPipeline(apiKey?: string) {
ssl => true
ssl_certificate_authorities => [""]
ssl_certificate => ""
- ssl_key => ""
+ ssl_key => ""
ssl_verify_mode => "force_peer"
}
}
@@ -27,7 +27,7 @@ output {
api_key => ""
data_stream => true
ssl => true
- # cacert:
+ # cacert => "