From d568da9225794d09355a7bee8767335a6ad6072b Mon Sep 17 00:00:00 2001 From: Candace Park <56409205+parkiino@users.noreply.github.com> Date: Wed, 3 Jun 2020 17:30:40 -0400 Subject: [PATCH] [ENDPOINT][INGEST]Task/endpoint ingest update (#67234) Custom endpoint Datasource configuration in ingest Co-authored-by: Elastic Machine Co-authored-by: Jen Huang --- .../ingest_manager/hooks/index.ts | 2 +- .../ingest_manager/hooks/use_core.ts | 16 ++--- .../applications/ingest_manager/index.tsx | 7 +- .../custom_configure_datasource.tsx | 61 ++++++++++++++++ .../components/index.ts | 1 + .../step_configure_datasource.tsx | 42 +++++------ .../edit_datasource_page/index.tsx | 5 +- x-pack/plugins/ingest_manager/public/index.ts | 8 +++ .../plugins/ingest_manager/public/plugin.ts | 10 ++- .../mock/endpoint/dependencies_start_mock.ts | 4 +- .../configure_datasource.tsx | 72 +++++++++++++++++++ x-pack/plugins/siem/public/plugin.tsx | 2 + 12 files changed, 186 insertions(+), 44 deletions(-) create mode 100644 x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/custom_configure_datasource.tsx create mode 100644 x-pack/plugins/siem/public/management/pages/policy/view/ingest_manager_integration/configure_datasource.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/index.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/index.ts index 31a511f2d79dc..6ebfd3f28fd9b 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/index.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/index.ts @@ -5,7 +5,7 @@ */ export { useCapabilities } from './use_capabilities'; -export { useCore, CoreContext } from './use_core'; +export { useCore } from './use_core'; export { useConfig, ConfigContext } from './use_config'; export { useSetupDeps, useStartDeps, DepsContext } from './use_deps'; export { useBreadcrumbs } from './use_breadcrumbs'; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_core.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_core.ts index f4e9a032b925a..9ce1e95aa91d5 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_core.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_core.ts @@ -4,15 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext } from 'react'; -import { CoreStart } from 'src/core/public'; +import { CoreStart } from 'kibana/public'; +import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; -export const CoreContext = React.createContext(null); - -export function useCore() { - const core = useContext(CoreContext); - if (core === null) { - throw new Error('CoreContext not initialized'); +export function useCore(): CoreStart { + const { services } = useKibana(); + if (services === null) { + throw new Error('KibanaContextProvider not initialized'); } - return core; + return services; } diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx index f6a386314272f..ed5a75ce6c991 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx @@ -22,11 +22,12 @@ import { PAGE_ROUTING_PATHS } from './constants'; import { DefaultLayout, WithoutHeaderLayout } from './layouts'; import { Loading, Error } from './components'; import { IngestManagerOverview, EPMApp, AgentConfigApp, FleetApp, DataStreamApp } from './sections'; -import { CoreContext, DepsContext, ConfigContext, setHttpClient, useConfig } from './hooks'; +import { DepsContext, ConfigContext, setHttpClient, useConfig } from './hooks'; import { PackageInstallProvider } from './sections/epm/hooks'; import { useCore, sendSetup, sendGetPermissionsCheck } from './hooks'; import { FleetStatusProvider } from './hooks/use_fleet_status'; import './index.scss'; +import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public'; export interface ProtectedRouteProps extends RouteProps { isAllowed?: boolean; @@ -229,7 +230,7 @@ const IngestManagerApp = ({ const isDarkMode = useObservable(coreStart.uiSettings.get$('theme:darkMode')); return ( - + @@ -237,7 +238,7 @@ const IngestManagerApp = ({ - + ); }; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/custom_configure_datasource.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/custom_configure_datasource.tsx new file mode 100644 index 0000000000000..aff764cb8ba3e --- /dev/null +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/custom_configure_datasource.tsx @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiEmptyPrompt, EuiText } from '@elastic/eui'; +import { NewDatasource } from '../../../../types'; +import { CreateDatasourceFrom } from '../types'; + +export interface CustomConfigureDatasourceProps { + packageName: string; + from: CreateDatasourceFrom; + datasource: NewDatasource | (NewDatasource & { id: string }); +} + +/** + * Custom content type that external plugins can provide to Ingest's + * Datasource configuration. + */ +export type CustomConfigureDatasourceContent = React.FC; + +type AllowedDatasourceKey = 'endpoint'; +const ConfigureDatasourceMapping: { + [key: string]: CustomConfigureDatasourceContent; +} = {}; + +/** + * Plugins can call this function from the start lifecycle to + * register a custom component in the Ingest Datasource configuration. + */ +export function registerDatasource( + key: AllowedDatasourceKey, + value: CustomConfigureDatasourceContent +) { + ConfigureDatasourceMapping[key] = value; +} + +const EmptyConfigureDatasource: CustomConfigureDatasourceContent = () => ( + +

+ +

+ + } + /> +); + +export const CustomConfigureDatasource = (props: CustomConfigureDatasourceProps) => { + const ConfigureDatasourceContent = + ConfigureDatasourceMapping[props.packageName] || EmptyConfigureDatasource; + return ; +}; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/index.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/index.ts index 3bfca75668911..42848cc0f5e41 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/index.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/index.ts @@ -6,3 +6,4 @@ export { CreateDatasourcePageLayout } from './layout'; export { DatasourceInputPanel } from './datasource_input_panel'; export { DatasourceInputVarField } from './datasource_input_var_field'; +export { CustomConfigureDatasource } from './custom_configure_datasource'; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_configure_datasource.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_configure_datasource.tsx index 58a98f86de426..d9cf0fbfb7987 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_configure_datasource.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_configure_datasource.tsx @@ -5,28 +5,29 @@ */ import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { - EuiPanel, - EuiFlexGroup, - EuiFlexItem, - EuiSpacer, - EuiEmptyPrompt, - EuiText, - EuiCallOut, -} from '@elastic/eui'; +import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiCallOut } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { PackageInfo, NewDatasource, DatasourceInput } from '../../../types'; import { Loading } from '../../../components'; import { DatasourceValidationResults, validationHasErrors } from './services'; -import { DatasourceInputPanel } from './components'; +import { DatasourceInputPanel, CustomConfigureDatasource } from './components'; +import { CreateDatasourceFrom } from './types'; export const StepConfigureDatasource: React.FunctionComponent<{ + from?: CreateDatasourceFrom; packageInfo: PackageInfo; - datasource: NewDatasource; + datasource: NewDatasource | (NewDatasource & { id: string }); updateDatasource: (fields: Partial) => void; validationResults: DatasourceValidationResults; submitAttempted: boolean; -}> = ({ packageInfo, datasource, updateDatasource, validationResults, submitAttempted }) => { +}> = ({ + from = 'config', + packageInfo, + datasource, + updateDatasource, + validationResults, + submitAttempted, +}) => { const hasErrors = validationResults ? validationHasErrors(validationResults) : false; // Configure inputs (and their streams) @@ -68,19 +69,10 @@ export const StepConfigureDatasource: React.FunctionComponent<{ ) : ( - -

- -

- - } +
); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_datasource_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_datasource_page/index.tsx index 7be955bc9f4f3..4bb42faedf7f6 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_datasource_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_datasource_page/index.tsx @@ -69,7 +69,8 @@ export const EditDatasourcePage: React.FunctionComponent = () => { const [loadingError, setLoadingError] = useState(); const [agentConfig, setAgentConfig] = useState(); const [packageInfo, setPackageInfo] = useState(); - const [datasource, setDatasource] = useState({ + const [datasource, setDatasource] = useState({ + id: '', name: '', description: '', config_id: '', @@ -93,7 +94,6 @@ export const EditDatasourcePage: React.FunctionComponent = () => { } if (datasourceData?.item) { const { - id, revision, inputs, created_by, @@ -299,6 +299,7 @@ export const EditDatasourcePage: React.FunctionComponent = () => { ), children: ( { return new IngestManagerPlugin(initializerContext); }; + +export { + CustomConfigureDatasourceContent, + CustomConfigureDatasourceProps, + registerDatasource, +} from './applications/ingest_manager/sections/agent_config/create_datasource_page/components/custom_configure_datasource'; + +export { NewDatasource } from './applications/ingest_manager/types'; diff --git a/x-pack/plugins/ingest_manager/public/plugin.ts b/x-pack/plugins/ingest_manager/public/plugin.ts index fd4e08f619495..3eb2fad339b7d 100644 --- a/x-pack/plugins/ingest_manager/public/plugin.ts +++ b/x-pack/plugins/ingest_manager/public/plugin.ts @@ -18,6 +18,7 @@ import { PLUGIN_ID } from '../common/constants'; import { IngestManagerConfigType } from '../common/types'; import { setupRouteService, appRoutesService } from '../common'; +import { registerDatasource } from './applications/ingest_manager/sections/agent_config/create_datasource_page/components/custom_configure_datasource'; export { IngestManagerConfigType } from '../common/types'; @@ -26,6 +27,7 @@ export type IngestManagerSetup = void; * Describes public IngestManager plugin contract returned at the `start` stage. */ export interface IngestManagerStart { + registerDatasource: typeof registerDatasource; success: boolean; error?: { message: string; @@ -80,12 +82,16 @@ export class IngestManagerPlugin const permissionsResponse = await core.http.get(appRoutesService.getCheckPermissionsPath()); if (permissionsResponse.success) { const { isInitialized: success } = await core.http.post(setupRouteService.getSetupPath()); - return { success }; + return { success, registerDatasource }; } else { throw new Error(permissionsResponse.error); } } catch (error) { - return { success: false, error: { message: error.body?.message || 'Unknown error' } }; + return { + success: false, + error: { message: error.body?.message || 'Unknown error' }, + registerDatasource, + }; } } diff --git a/x-pack/plugins/siem/public/common/mock/endpoint/dependencies_start_mock.ts b/x-pack/plugins/siem/public/common/mock/endpoint/dependencies_start_mock.ts index d3fc653f4c9ba..759ec45c7e54b 100644 --- a/x-pack/plugins/siem/public/common/mock/endpoint/dependencies_start_mock.ts +++ b/x-pack/plugins/siem/public/common/mock/endpoint/dependencies_start_mock.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IngestManagerStart } from '../../../../../ingest_manager/public'; +import { IngestManagerStart, registerDatasource } from '../../../../../ingest_manager/public'; import { dataPluginMock, Start as DataPublicStartMock, @@ -56,6 +56,6 @@ export const depsStartMock: () => DepsStartMock = () => { return { data: dataMock, - ingestManager: { success: true }, + ingestManager: { success: true, registerDatasource }, }; }; diff --git a/x-pack/plugins/siem/public/management/pages/policy/view/ingest_manager_integration/configure_datasource.tsx b/x-pack/plugins/siem/public/management/pages/policy/view/ingest_manager_integration/configure_datasource.tsx new file mode 100644 index 0000000000000..bbdeb21254536 --- /dev/null +++ b/x-pack/plugins/siem/public/management/pages/policy/view/ingest_manager_integration/configure_datasource.tsx @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { memo } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiEmptyPrompt, EuiText } from '@elastic/eui'; +import { useKibana } from '../../../../../../../../../src/plugins/kibana_react/public'; +import { LinkToApp } from '../../../../../common/components/endpoint/link_to_app'; +import { + CustomConfigureDatasourceContent, + CustomConfigureDatasourceProps, + NewDatasource, +} from '../../../../../../../ingest_manager/public'; +import { getManagementUrl } from '../../../..'; + +type DatasourceWithId = NewDatasource & { id: string }; + +/** + * Exports Endpoint-specific datasource configuration instructions + * for use in the Ingest app create / edit datasource config + */ +export const ConfigureEndpointDatasource = memo( + ({ + from, + datasource, + }: { + from: string; + datasource: CustomConfigureDatasourceProps['datasource']; + }) => { + const { services } = useKibana(); + let policyUrl = ''; + if (from === 'edit') { + policyUrl = getManagementUrl({ + name: 'policyDetails', + policyId: (datasource as DatasourceWithId).id, + }); + } + + return ( + +

+ {from === 'edit' ? ( + + + + ) : ( + + )} +

+ + } + /> + ); + } +); + +ConfigureEndpointDatasource.displayName = 'ConfigureEndpointDatasource'; diff --git a/x-pack/plugins/siem/public/plugin.tsx b/x-pack/plugins/siem/public/plugin.tsx index 4b8fc078fc016..b4e0de4ff316d 100644 --- a/x-pack/plugins/siem/public/plugin.tsx +++ b/x-pack/plugins/siem/public/plugin.tsx @@ -20,6 +20,7 @@ import { KibanaServices } from './common/lib/kibana/services'; import { serviceNowActionType, jiraActionType } from './common/lib/connectors'; import { PluginSetup, PluginStart, SetupPlugins, StartPlugins, StartServices } from './types'; import { APP_ID, APP_NAME, APP_ICON, APP_PATH } from '../common/constants'; +import { ConfigureEndpointDatasource } from './management/pages/policy/view/ingest_manager_integration/configure_datasource'; export class Plugin implements IPlugin { private kibanaVersion: string; @@ -131,6 +132,7 @@ export class Plugin implements IPlugin