From 6628232433c0144f7564b22d8e6d2941425431ae Mon Sep 17 00:00:00 2001 From: Bena Kansara <69037875+benakansara@users.noreply.github.com> Date: Thu, 7 Dec 2023 13:05:01 +0530 Subject: [PATCH 1/4] Deprecate feature flag for Log threshold alert details page (#172554) Resolves https://github.com/elastic/kibana/issues/172379 - Deprecates following feature flag used for enabling/disabling Log threshold alert details page: ``` xpack.observability.unsafe.alertDetails.logs.enabled ``` - Removes usage of this flag from code. - Adding this flag in `kibana.yml` will generate following warning: ``` [WARN ][config.deprecation] You no longer need to configure "xpack.observability.unsafe.alertDetails.logs.enabled". ``` --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/README.md | 6 ---- .../log_threshold/log_threshold_executor.ts | 31 ++----------------- .../public/application/application.test.tsx | 1 - .../alert_details/alert_details.test.tsx | 1 - .../public/pages/alerts/alerts.test.tsx | 1 - .../alerts/components/alert_actions.test.tsx | 1 - .../sections/apm/apm_section.test.tsx | 1 - .../pages/overview/overview.stories.tsx | 1 - .../public/pages/rules/rules.test.tsx | 1 - x-pack/plugins/observability/public/plugin.ts | 2 +- .../utils/is_alert_details_enabled.test.ts | 13 +------- .../public/utils/is_alert_details_enabled.ts | 6 ++-- .../kibana_react.storybook_decorator.tsx | 1 - .../public/utils/test_helper.tsx | 1 - x-pack/plugins/observability/server/index.ts | 4 +-- 15 files changed, 10 insertions(+), 61 deletions(-) diff --git a/x-pack/README.md b/x-pack/README.md index ea8777f46b143..255a4d3e2b6e8 100644 --- a/x-pack/README.md +++ b/x-pack/README.md @@ -14,12 +14,6 @@ xpack.observability.unsafe.alertDetails.metrics.enabled: true **[For Infrastructure rule types]** In Kibana configuration, will allow the user to navigate to the new Alert Details page, instead of the Alert Flyout when clicking on `View alert details` in the Alert table -```yaml -xpack.observability.unsafe.alertDetails.logs.enabled: true -``` - -**[For Logs threshold rule type]** In Kibana configuration, will allow the user to navigate to the new Alert Details page, instead of the Alert Flyout when clicking on `View alert details` in the Alert table - ```yaml xpack.observability.unsafe.alertDetails.uptime.enabled: true ``` 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 e36ae54746b3d..517b020eaeace 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 @@ -7,11 +7,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { i18n } from '@kbn/i18n'; -import { - AlertsLocatorParams, - getAlertDetailsUrl, - getAlertUrl, -} from '@kbn/observability-plugin/common'; +import { AlertsLocatorParams, getAlertDetailsUrl } from '@kbn/observability-plugin/common'; import { ALERT_CONTEXT, ALERT_EVALUATION_THRESHOLD, @@ -63,7 +59,6 @@ import { InfraBackendLibs } from '../../infra_types'; import { AdditionalContext, flattenAdditionalContext, - getAlertDetailsPageEnabledForApp, getContextForRecoveredAlerts, getGroupByObject, unflattenObject, @@ -138,7 +133,6 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) => getAlertByAlertUuid, } = services; const { basePath, alertsLocator } = libs; - const config = libs.getAlertDetailsConfig(); const alertFactory: LogThresholdAlertFactory = ( id, @@ -189,15 +183,7 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) => alert.scheduleActions(actionGroup, { ...sharedContext, ...context, - alertDetailsUrl: getAlertDetailsPageEnabledForApp(config, 'logs') - ? getAlertDetailsUrl(libs.basePath, spaceId, alertUuid) - : await getAlertUrl( - alertUuid, - spaceId, - indexedStartedAt, - libs.alertsLocator, - libs.basePath.publicBaseUrl - ), + alertDetailsUrl: getAlertDetailsUrl(libs.basePath, spaceId, alertUuid), }); }); } @@ -254,7 +240,6 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) => validatedParams, getAlertByAlertUuid, alertsLocator, - isAlertDetailsPageEnabled: getAlertDetailsPageEnabledForApp(config, 'logs'), }); } catch (e) { throw new Error(e); @@ -868,7 +853,6 @@ const processRecoveredAlerts = async ({ validatedParams, getAlertByAlertUuid, alertsLocator, - isAlertDetailsPageEnabled = false, }: { basePath: IBasePath; getAlertStartedDate: (alertId: string) => string | null; @@ -881,7 +865,6 @@ const processRecoveredAlerts = async ({ alertUuid: string ) => Promise | null> | null; alertsLocator?: LocatorPublic; - isAlertDetailsPageEnabled?: boolean; }) => { const groupByKeysObjectForRecovered = getGroupByObject( validatedParams.groupBy, @@ -898,15 +881,7 @@ const processRecoveredAlerts = async ({ const viewInAppUrl = addSpaceIdToPath(basePath.publicBaseUrl, spaceId, relativeViewInAppUrl); const baseContext = { - alertDetailsUrl: isAlertDetailsPageEnabled - ? getAlertDetailsUrl(basePath, spaceId, alertUuid) - : await getAlertUrl( - alertUuid, - spaceId, - indexedStartedAt, - alertsLocator, - basePath.publicBaseUrl - ), + alertDetailsUrl: getAlertDetailsUrl(basePath, spaceId, alertUuid), group: hasGroupBy(validatedParams) ? recoveredAlertId : null, groupByKeys: groupByKeysObjectForRecovered[recoveredAlertId], timestamp: startedAt.toISOString(), diff --git a/x-pack/plugins/observability/public/application/application.test.tsx b/x-pack/plugins/observability/public/application/application.test.tsx index eb7da89d3441d..3b385fee702f5 100644 --- a/x-pack/plugins/observability/public/application/application.test.tsx +++ b/x-pack/plugins/observability/public/application/application.test.tsx @@ -77,7 +77,6 @@ describe('renderApp', () => { const config = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, }, diff --git a/x-pack/plugins/observability/public/pages/alert_details/alert_details.test.tsx b/x-pack/plugins/observability/public/pages/alert_details/alert_details.test.tsx index 756f90ecd97cf..f2a7a4d72d66f 100644 --- a/x-pack/plugins/observability/public/pages/alert_details/alert_details.test.tsx +++ b/x-pack/plugins/observability/public/pages/alert_details/alert_details.test.tsx @@ -90,7 +90,6 @@ const params = { const config: Subset = { unsafe: { alertDetails: { - logs: { enabled: true }, metrics: { enabled: true }, uptime: { enabled: true }, }, diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts.test.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts.test.tsx index 247a700acfa6c..28b4c7b2a3d73 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts.test.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts.test.tsx @@ -53,7 +53,6 @@ jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({ slo: { enabled: false }, alertDetails: { apm: { enabled: false }, - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, observability: { enabled: false }, diff --git a/x-pack/plugins/observability/public/pages/alerts/components/alert_actions.test.tsx b/x-pack/plugins/observability/public/pages/alerts/components/alert_actions.test.tsx index cbdb9aa068dad..b8e216ded52fb 100644 --- a/x-pack/plugins/observability/public/pages/alerts/components/alert_actions.test.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/components/alert_actions.test.tsx @@ -59,7 +59,6 @@ jest.mock('@kbn/triggers-actions-ui-plugin/public/common/lib/kibana/kibana_react const config = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, }, diff --git a/x-pack/plugins/observability/public/pages/overview/components/sections/apm/apm_section.test.tsx b/x-pack/plugins/observability/public/pages/overview/components/sections/apm/apm_section.test.tsx index 6da498042f8fb..23d3af1167b99 100644 --- a/x-pack/plugins/observability/public/pages/overview/components/sections/apm/apm_section.test.tsx +++ b/x-pack/plugins/observability/public/pages/overview/components/sections/apm/apm_section.test.tsx @@ -48,7 +48,6 @@ describe('APMSection', () => { const config = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, }, diff --git a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx index d0937d1f2c72b..3114c084be289 100644 --- a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx +++ b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx @@ -81,7 +81,6 @@ const withCore = makeDecorator({ const config: ConfigSchema = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, observability: { enabled: false }, diff --git a/x-pack/plugins/observability/public/pages/rules/rules.test.tsx b/x-pack/plugins/observability/public/pages/rules/rules.test.tsx index 8be89be03d57b..3b36403c4e18f 100644 --- a/x-pack/plugins/observability/public/pages/rules/rules.test.tsx +++ b/x-pack/plugins/observability/public/pages/rules/rules.test.tsx @@ -40,7 +40,6 @@ jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({ slo: { enabled: false }, alertDetails: { apm: { enabled: false }, - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, observability: { enabled: false }, diff --git a/x-pack/plugins/observability/public/plugin.ts b/x-pack/plugins/observability/public/plugin.ts index 12848e1bb4974..b6c17e0c3f914 100644 --- a/x-pack/plugins/observability/public/plugin.ts +++ b/x-pack/plugins/observability/public/plugin.ts @@ -94,7 +94,7 @@ export interface ConfigSchema { metrics: { enabled: boolean; }; - logs: { + logs?: { enabled: boolean; }; uptime: { diff --git a/x-pack/plugins/observability/public/utils/is_alert_details_enabled.test.ts b/x-pack/plugins/observability/public/utils/is_alert_details_enabled.test.ts index a39c4cd00b576..101e10a314451 100644 --- a/x-pack/plugins/observability/public/utils/is_alert_details_enabled.test.ts +++ b/x-pack/plugins/observability/public/utils/is_alert_details_enabled.test.ts @@ -31,7 +31,6 @@ import type { TopAlert } from '../typings/alerts'; const defaultConfig = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, }, @@ -63,15 +62,10 @@ describe('isAlertDetailsEnabled', () => { start: 1630587249674, lastUpdated: 1630588131750, } as unknown as TopAlert; - it('returns FALSE when logs: { enabled: false }', () => { - expect(isAlertDetailsEnabledPerApp(logsAlert, defaultConfig)).toBeFalsy(); - }); - - it('returns TRUE when logs: { enabled: true }', () => { + it('returns TRUE when rule type is logs.alert.document.count', () => { const updatedConfig = { unsafe: { alertDetails: { - logs: { enabled: true }, metrics: { enabled: false }, uptime: { enabled: false }, }, @@ -113,7 +107,6 @@ describe('isAlertDetailsEnabled', () => { const updatedConfig = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, }, @@ -159,7 +152,6 @@ describe('isAlertDetailsEnabled', () => { const updatedConfig = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: true }, uptime: { enabled: false }, }, @@ -201,7 +193,6 @@ describe('isAlertDetailsEnabled', () => { const updatedConfig = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: true }, }, @@ -243,7 +234,6 @@ describe('isAlertDetailsEnabled', () => { const updatedConfig = { unsafe: { alertDetails: { - logs: { enabled: true }, metrics: { enabled: true }, uptime: { enabled: true }, }, @@ -255,7 +245,6 @@ describe('isAlertDetailsEnabled', () => { const updatedConfig = { unsafe: { alertDetails: { - logs: { enabled: true }, metrics: { enabled: true }, uptime: { enabled: true }, }, diff --git a/x-pack/plugins/observability/public/utils/is_alert_details_enabled.ts b/x-pack/plugins/observability/public/utils/is_alert_details_enabled.ts index 15b9589be60f6..2b628f26ee794 100644 --- a/x-pack/plugins/observability/public/utils/is_alert_details_enabled.ts +++ b/x-pack/plugins/observability/public/utils/is_alert_details_enabled.ts @@ -9,12 +9,12 @@ import { ALERT_RULE_TYPE_ID } from '@kbn/rule-data-utils'; import type { ConfigSchema } from '../plugin'; import type { TopAlert } from '../typings/alerts'; -const ALLOWED_RULE_TYPES = ['apm.transaction_duration']; +const ALLOWED_RULE_TYPES = ['apm.transaction_duration', 'logs.alert.document.count']; const isUnsafeAlertDetailsFlag = ( subject: string -): subject is keyof ConfigSchema['unsafe']['alertDetails'] => - ['uptime', 'logs', 'metrics', 'observability'].includes(subject); +): subject is keyof Omit => + ['uptime', 'metrics', 'observability'].includes(subject); // We are mapping the ruleTypeId from the feature flag with the ruleTypeId from the alert // to know whether the feature flag is enabled or not. diff --git a/x-pack/plugins/observability/public/utils/kibana_react.storybook_decorator.tsx b/x-pack/plugins/observability/public/utils/kibana_react.storybook_decorator.tsx index d5714924bdc97..8b8f65e244ddf 100644 --- a/x-pack/plugins/observability/public/utils/kibana_react.storybook_decorator.tsx +++ b/x-pack/plugins/observability/public/utils/kibana_react.storybook_decorator.tsx @@ -28,7 +28,6 @@ export function KibanaReactStorybookDecorator(Story: ComponentType) { const config: ConfigSchema = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, observability: { enabled: false }, diff --git a/x-pack/plugins/observability/public/utils/test_helper.tsx b/x-pack/plugins/observability/public/utils/test_helper.tsx index 6c1610ac059c9..12fa672552db9 100644 --- a/x-pack/plugins/observability/public/utils/test_helper.tsx +++ b/x-pack/plugins/observability/public/utils/test_helper.tsx @@ -32,7 +32,6 @@ export const data = dataPluginMock.createStartContract(); const defaultConfig: ConfigSchema = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, observability: { enabled: false }, diff --git a/x-pack/plugins/observability/server/index.ts b/x-pack/plugins/observability/server/index.ts index ce2279db23203..da4797f42c43f 100644 --- a/x-pack/plugins/observability/server/index.ts +++ b/x-pack/plugins/observability/server/index.ts @@ -36,8 +36,7 @@ const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: false }), }), logs: schema.object({ - // Enable it by default: https://github.com/elastic/kibana/issues/159945 - enabled: schema.boolean({ defaultValue: true }), + enabled: schema.boolean({ defaultValue: false }), }), uptime: schema.object({ enabled: schema.boolean({ defaultValue: false }), @@ -71,6 +70,7 @@ export const config: PluginConfigDescriptor = { }, }, schema: configSchema, + deprecations: ({ unused }) => [unused('unsafe.alertDetails.logs.enabled', { level: 'warning' })], }; export type ObservabilityConfig = TypeOf; From df8037288811958dadcfd08b79e4831919264c44 Mon Sep 17 00:00:00 2001 From: Maxim Kholod Date: Thu, 7 Dec 2023 10:07:37 +0100 Subject: [PATCH 2/4] [Cloud Security] CSPM AWS agentless selector (#171671) ## Summary A part of - https://github.com/elastic/security-team/issues/7969 This PR doesn't cover the fact that with Agentless only `Manual - Direct Access Key` and `Manual - Temprary access key` are supported. Hiding other setup options, like `Cloudformation`, `Manual - Assume role` or Manual - Shared Credentials`, will be resolved in the next PR. As this feature is hidden behind a feature flag and based on the fact that Agentless is available only for a handful of internal Cloud org ids, it should be safe to merge this PR if code-wise it's ok. ### How to test Make sure to have the FF in your `serverless.security.dev.yml` (it's basically the `kibana.dev.yml` but specifically for Serverless Security Projects) enabled. Also specify some serverless project id, to enable the logic of `isServerlessEnabled` ``` xpack.fleet.enableExperimental: ['agentless'] xpack.cloud.serverless.project_id: 'some_fake_project_id' ``` Follow the steps from this comment https://github.com/elastic/security-team/issues/7972#issuecomment-1808096052 to have the Agentless artifacts (agent, policy, output, and fleet server host) locally After that, you should be able to test the flow. Mind that with agentless only `Manual - Direct Access Key` and `Manual - Temprary access key` setup methods are available. Hiding other options will be addressed in the follow ups ### Screencast [screencast-maxcold-agentless-selector-pr-b5b706.kb.eu-west-1.aws.qa.elastic.cloud-2023.11.27-10_30_57.webm](https://github.com/elastic/kibana/assets/478762/b3abd216-0863-4081-8643-cda0688757f6) ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [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 --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../fleet_extensions/policy_template_form.tsx | 36 +++- .../setup_technology_selector.tsx | 128 +++++++++++ .../use_setup_technology.test.ts | 59 +++++ .../use_setup_technology.ts | 64 ++++++ .../fleet/common/experimental_features.ts | 1 + .../fleet/common/types/models/index.ts | 1 + .../common/types/models/setup_technology.ts | 11 + .../single_page_layout/hooks/index.tsx | 1 + .../hooks/setup_technology.test.ts | 204 ++++++++++++++++++ .../hooks/setup_technology.ts | 86 ++++++++ .../single_page_layout/index.tsx | 54 +++-- x-pack/plugins/fleet/public/index.ts | 1 + x-pack/plugins/fleet/public/types/index.ts | 1 + .../fleet/public/types/ui_extensions.ts | 2 + 14 files changed, 624 insertions(+), 25 deletions(-) create mode 100644 x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/setup_technology_selector/setup_technology_selector.tsx create mode 100644 x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/setup_technology_selector/use_setup_technology.test.ts create mode 100644 x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/setup_technology_selector/use_setup_technology.ts create mode 100644 x-pack/plugins/fleet/common/types/models/setup_technology.ts create mode 100644 x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts create mode 100644 x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx index 163857b27e0f9..25360d33d1114 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx @@ -32,7 +32,7 @@ import { i18n } from '@kbn/i18n'; import { AZURE_ARM_TEMPLATE_CREDENTIAL_TYPE } from './azure_credentials_form/azure_credentials_form'; import { CspRadioGroupProps, RadioGroup } from './csp_boxed_radio_group'; import { assert } from '../../../common/utils/helpers'; -import type { PostureInput, CloudSecurityPolicyTemplate } from '../../../common/types'; +import type { CloudSecurityPolicyTemplate, PostureInput } from '../../../common/types'; import { CLOUDBEAT_AWS, CLOUDBEAT_VANILLA, @@ -41,14 +41,14 @@ import { SUPPORTED_POLICY_TEMPLATES, } from '../../../common/constants'; import { - getPosturePolicy, + getMaxPackageName, getPostureInputHiddenVars, + getPosturePolicy, getVulnMgmtCloudFormationDefaultValue, - POSTURE_NAMESPACE, - type NewPackagePolicyPostureInput, isPostureInput, - getMaxPackageName, isBelowMinVersion, + type NewPackagePolicyPostureInput, + POSTURE_NAMESPACE, } from './utils'; import { PolicyTemplateInfo, @@ -58,6 +58,8 @@ import { } from './policy_template_selectors'; import { usePackagePolicyList } from '../../common/api/use_package_policy_list'; import { gcpField, getInputVarsFields } from './gcp_credential_form'; +import { SetupTechnologySelector } from './setup_technology_selector/setup_technology_selector'; +import { useSetupTechnology } from './setup_technology_selector/use_setup_technology'; const DEFAULT_INPUT_TYPE = { kspm: CLOUDBEAT_VANILLA, @@ -520,7 +522,16 @@ const IntegrationSettings = ({ onChange, fields }: IntegrationInfoFieldsProps) = ); export const CspPolicyTemplateForm = memo( - ({ newPolicy, onChange, validationResults, isEditPage, packageInfo }) => { + ({ + agentPolicy, + newPolicy, + onChange, + validationResults, + isEditPage, + packageInfo, + handleSetupTechnologyChange, + agentlessPolicy, + }) => { const integrationParam = useParams<{ integration: CloudSecurityPolicyTemplate }>().integration; const integration = SUPPORTED_POLICY_TEMPLATES.includes(integrationParam) ? integrationParam @@ -528,6 +539,12 @@ export const CspPolicyTemplateForm = memo { @@ -722,6 +739,13 @@ export const CspPolicyTemplateForm = memo updatePolicy({ ...newPolicy, [field]: value })} /> + {isAgentlessAvailable && ( + + )} + {/* Defines the vars of the enabled input of the active policy template */} void; +}) => { + const options = [ + { + value: SetupTechnology.AGENTLESS, + inputDisplay: ( + + ), + dropdownDisplay: ( + <> + + + + +

+ +

+
+ + ), + }, + { + value: SetupTechnology.AGENT_BASED, + inputDisplay: ( + + ), + dropdownDisplay: ( + <> + + + + +

+ +

+
+ + ), + }, + ]; + + return ( + <> + + + + + } + > + + + } + > + + } + onChange={onSetupTechnologyChange} + itemLayoutAlign="top" + hasDividers + fullWidth + /> + + + + ); +}; diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/setup_technology_selector/use_setup_technology.test.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/setup_technology_selector/use_setup_technology.test.ts new file mode 100644 index 0000000000000..a5aa5e2df9734 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/setup_technology_selector/use_setup_technology.test.ts @@ -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 { renderHook, act } from '@testing-library/react-hooks'; + +import { SetupTechnology } from '@kbn/fleet-plugin/public'; +import { AgentPolicy, NewPackagePolicyInput } from '@kbn/fleet-plugin/common'; + +import { CLOUDBEAT_AWS } from '../../../../common/constants'; +import { useSetupTechnology } from './use_setup_technology'; + +describe('useSetupTechnology', () => { + it('initializes with AGENT_BASED technology', () => { + const { result } = renderHook(() => + useSetupTechnology({ + input: { type: 'cloudbeat/no-agentless-support' } as NewPackagePolicyInput, + }) + ); + expect(result.current.setupTechnology).toBe(SetupTechnology.AGENT_BASED); + }); + + it('sets to AGENTLESS when agentless is available', () => { + const agentlessPolicy = { id: 'agentlessPolicyId' } as AgentPolicy; + const input = { type: CLOUDBEAT_AWS } as NewPackagePolicyInput; + const { result } = renderHook(() => useSetupTechnology({ input, agentlessPolicy })); + expect(result.current.isAgentlessAvailable).toBeTruthy(); + expect(result.current.setupTechnology).toBe(SetupTechnology.AGENTLESS); + }); + + it('sets to AGENT_BASED when agentPolicyId differs from agentlessPolicyId', () => { + const input = { type: CLOUDBEAT_AWS } as NewPackagePolicyInput; + const agentPolicy = { id: 'agentPolicyId' } as AgentPolicy; + const agentlessPolicy = { id: 'agentlessPolicyId' } as AgentPolicy; + const { result } = renderHook(() => + useSetupTechnology({ input, agentPolicy, agentlessPolicy }) + ); + expect(result.current.setupTechnology).toBe(SetupTechnology.AGENT_BASED); + }); + + it('calls handleSetupTechnologyChange when setupTechnology changes', () => { + const handleSetupTechnologyChangeMock = jest.fn(); + const { result } = renderHook(() => + useSetupTechnology({ + input: { type: 'someType' } as NewPackagePolicyInput, + handleSetupTechnologyChange: handleSetupTechnologyChangeMock, + }) + ); + + act(() => { + result.current.setSetupTechnology(SetupTechnology.AGENTLESS); + }); + + expect(handleSetupTechnologyChangeMock).toHaveBeenCalledWith(SetupTechnology.AGENTLESS); + }); +}); diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/setup_technology_selector/use_setup_technology.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/setup_technology_selector/use_setup_technology.ts new file mode 100644 index 0000000000000..898017d6daef5 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/setup_technology_selector/use_setup_technology.ts @@ -0,0 +1,64 @@ +/* + * 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, useMemo, useState } from 'react'; + +import { AgentPolicy, NewPackagePolicyInput } from '@kbn/fleet-plugin/common'; +import { SetupTechnology } from '@kbn/fleet-plugin/public'; +import { CLOUDBEAT_AWS } from '../../../../common/constants'; + +export const useSetupTechnology = ({ + input, + agentPolicy, + agentlessPolicy, + handleSetupTechnologyChange, +}: { + input: NewPackagePolicyInput; + agentPolicy?: AgentPolicy; + agentlessPolicy?: AgentPolicy; + handleSetupTechnologyChange?: (value: SetupTechnology) => void; +}) => { + const [setupTechnology, setSetupTechnology] = useState( + SetupTechnology.AGENT_BASED + ); + const isCspmAws = input.type === CLOUDBEAT_AWS; + const isAgentlessAvailable = useMemo( + () => Boolean(isCspmAws && agentlessPolicy), + [isCspmAws, agentlessPolicy] + ); + const agentPolicyId = useMemo(() => agentPolicy?.id, [agentPolicy]); + const agentlessPolicyId = useMemo(() => agentlessPolicy?.id, [agentlessPolicy]); + + useEffect(() => { + if (agentPolicyId && agentPolicyId !== agentlessPolicyId) { + /* + handle case when agent policy is coming from outside, + e.g. from the get param or when coming to integration from a specific agent policy + */ + setSetupTechnology(SetupTechnology.AGENT_BASED); + } else if (isAgentlessAvailable) { + /* + preselecting agenteless when available + and resetting to agent-based when switching to another integration type, which doesn't support agentless + */ + setSetupTechnology(SetupTechnology.AGENTLESS); + } else { + setSetupTechnology(SetupTechnology.AGENT_BASED); + } + }, [agentPolicyId, agentlessPolicyId, isAgentlessAvailable]); + + useEffect(() => { + if (handleSetupTechnologyChange) { + handleSetupTechnologyChange(setupTechnology); + } + }, [handleSetupTechnologyChange, setupTechnology]); + + return { + isAgentlessAvailable, + setupTechnology, + setSetupTechnology, + }; +}; diff --git a/x-pack/plugins/fleet/common/experimental_features.ts b/x-pack/plugins/fleet/common/experimental_features.ts index 3ac7abb927b95..0c4a6b91fdb83 100644 --- a/x-pack/plugins/fleet/common/experimental_features.ts +++ b/x-pack/plugins/fleet/common/experimental_features.ts @@ -25,6 +25,7 @@ export const allowedExperimentalValues = Object.freeze>( kafkaOutput: true, outputSecretsStorage: true, remoteESOutput: true, + agentless: false, }); type ExperimentalConfigKeys = Array; diff --git a/x-pack/plugins/fleet/common/types/models/index.ts b/x-pack/plugins/fleet/common/types/models/index.ts index babbe3a8ce1ac..5af1294e52657 100644 --- a/x-pack/plugins/fleet/common/types/models/index.ts +++ b/x-pack/plugins/fleet/common/types/models/index.ts @@ -19,3 +19,4 @@ export * from './download_sources'; export * from './fleet_server_policy_config'; export * from './fleet_proxy'; export * from './secret'; +export * from './setup_technology'; diff --git a/x-pack/plugins/fleet/common/types/models/setup_technology.ts b/x-pack/plugins/fleet/common/types/models/setup_technology.ts new file mode 100644 index 0000000000000..66fb4a09ff9a2 --- /dev/null +++ b/x-pack/plugins/fleet/common/types/models/setup_technology.ts @@ -0,0 +1,11 @@ +/* + * 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 enum SetupTechnology { + AGENTLESS = 'agentless', + AGENT_BASED = 'agent-based', +} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/index.tsx index 33d1cee841590..2d8b96c562e85 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/index.tsx @@ -7,3 +7,4 @@ export { useDevToolsRequest } from './devtools_request'; export { useOnSubmit } from './form'; +export { useSetupTechnology } from './setup_technology'; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts new file mode 100644 index 0000000000000..dd2a1dcc81c79 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts @@ -0,0 +1,204 @@ +/* + * 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 { renderHook, act } from '@testing-library/react-hooks'; + +import { SetupTechnology } from '../../../../../../../../common/types'; +import { ExperimentalFeaturesService } from '../../../../../services'; +import { sendGetOneAgentPolicy, useStartServices } from '../../../../../hooks'; +import { SelectedPolicyTab } from '../../components'; + +import { useSetupTechnology } from './setup_technology'; + +jest.mock('../../../../../services'); +jest.mock('../../../../../hooks', () => ({ + ...jest.requireActual('../../../../../hooks'), + sendGetOneAgentPolicy: jest.fn(), + useStartServices: jest.fn(), +})); + +type MockFn = jest.MockedFunction; + +describe('useSetupTechnology', () => { + const updateNewAgentPolicyMock = jest.fn(); + const updateAgentPolicyMock = jest.fn(); + const setSelectedPolicyTabMock = jest.fn(); + const newAgentPolicyMock = { + name: 'mock_new_agent_policy', + namespace: 'default', + }; + const mockedExperimentalFeaturesService = jest.mocked(ExperimentalFeaturesService); + + beforeEach(() => { + mockedExperimentalFeaturesService.get.mockReturnValue({ + agentless: true, + } as any); + (sendGetOneAgentPolicy as MockFn).mockResolvedValue({ + data: { + item: { id: 'agentless-policy-id' }, + }, + }); + (useStartServices as MockFn).mockReturnValue({ + cloud: { + isServerlessEnabled: true, + }, + }); + jest.clearAllMocks(); + }); + + it('should initialize with default values when agentless is disabled', () => { + mockedExperimentalFeaturesService.get.mockReturnValue({ + agentless: false, + } as any); + + const { result } = renderHook(() => + useSetupTechnology({ + updateNewAgentPolicy: updateNewAgentPolicyMock, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicy: updateAgentPolicyMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + }) + ); + + expect(sendGetOneAgentPolicy).not.toHaveBeenCalled(); + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + expect(result.current.agentlessPolicy).toBeUndefined(); + }); + + it('should fetch agentless policy if agentless is enabled', async () => { + const { result, waitForNextUpdate } = renderHook(() => + useSetupTechnology({ + updateNewAgentPolicy: updateNewAgentPolicyMock, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicy: updateAgentPolicyMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + }) + ); + + await waitForNextUpdate(); + + expect(result.current.agentlessPolicy).toEqual({ id: 'agentless-policy-id' }); + }); + + it('should not fetch agentless policy if agentless is enabled but serverless is disabled', async () => { + (useStartServices as MockFn).mockReturnValue({ + cloud: { + isServerlessEnabled: false, + }, + }); + + const { result } = renderHook(() => + useSetupTechnology({ + updateNewAgentPolicy: updateNewAgentPolicyMock, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicy: updateAgentPolicyMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + }) + ); + + expect(sendGetOneAgentPolicy).not.toHaveBeenCalled(); + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + expect(result.current.agentlessPolicy).toBeUndefined(); + }); + + it('should update agent policy and selected policy tab when setup technology is agentless', async () => { + const { result, waitForNextUpdate } = renderHook(() => + useSetupTechnology({ + updateNewAgentPolicy: updateNewAgentPolicyMock, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicy: updateAgentPolicyMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + }) + ); + + await waitForNextUpdate(); + + act(() => { + result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS); + }); + + expect(updateAgentPolicyMock).toHaveBeenCalledWith({ id: 'agentless-policy-id' }); + expect(setSelectedPolicyTabMock).toHaveBeenCalledWith(SelectedPolicyTab.EXISTING); + }); + + it('should update new agent policy and selected policy tab when setup technology is agent-based', async () => { + const { result, waitForNextUpdate } = renderHook(() => + useSetupTechnology({ + updateNewAgentPolicy: updateNewAgentPolicyMock, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicy: updateAgentPolicyMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + }) + ); + + await waitForNextUpdate(); + + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + + act(() => { + result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS); + }); + + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENTLESS); + + act(() => { + result.current.handleSetupTechnologyChange(SetupTechnology.AGENT_BASED); + }); + + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + + expect(updateNewAgentPolicyMock).toHaveBeenCalledWith(newAgentPolicyMock); + expect(setSelectedPolicyTabMock).toHaveBeenCalledWith(SelectedPolicyTab.NEW); + }); + + it('should not update agent policy and selected policy tab when agentless is disabled', async () => { + mockedExperimentalFeaturesService.get.mockReturnValue({ + agentless: false, + } as any); + + const { result } = renderHook(() => + useSetupTechnology({ + updateNewAgentPolicy: updateNewAgentPolicyMock, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicy: updateAgentPolicyMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + }) + ); + + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + + act(() => { + result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS); + }); + + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + }); + + it('should not update agent policy and selected policy tab when setup technology matches the current one ', async () => { + const { result, waitForNextUpdate } = renderHook(() => + useSetupTechnology({ + updateNewAgentPolicy: updateNewAgentPolicyMock, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicy: updateAgentPolicyMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + }) + ); + + await waitForNextUpdate(); + + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + + act(() => { + result.current.handleSetupTechnologyChange(SetupTechnology.AGENT_BASED); + }); + + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + + expect(updateNewAgentPolicyMock).not.toHaveBeenCalled(); + expect(setSelectedPolicyTabMock).not.toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts new file mode 100644 index 0000000000000..22972f4a9a6d4 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts @@ -0,0 +1,86 @@ +/* + * 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 { useCallback, useEffect, useState } from 'react'; + +import { ExperimentalFeaturesService } from '../../../../../services'; +import type { AgentPolicy, NewAgentPolicy } from '../../../../../types'; +import { SetupTechnology } from '../../../../../types'; +import { sendGetOneAgentPolicy, useStartServices } from '../../../../../hooks'; +import { SelectedPolicyTab } from '../../components'; + +const AGENTLESS_POLICY_ID = 'agentless'; + +export function useSetupTechnology({ + updateNewAgentPolicy, + newAgentPolicy, + updateAgentPolicy, + setSelectedPolicyTab, +}: { + updateNewAgentPolicy: (policy: NewAgentPolicy) => void; + newAgentPolicy: NewAgentPolicy; + updateAgentPolicy: (policy: AgentPolicy) => void; + setSelectedPolicyTab: (tab: SelectedPolicyTab) => void; +}) { + const { agentless: isAgentlessEnabled } = ExperimentalFeaturesService.get(); + const { cloud } = useStartServices(); + const isServerless = cloud?.isServerlessEnabled ?? false; + const [selectedSetupTechnology, setSelectedSetupTechnology] = useState( + SetupTechnology.AGENT_BASED + ); + const [agentlessPolicy, setAgentlessPolicy] = useState(); + + useEffect(() => { + const fetchAgentlessPolicy = async () => { + const { data, error } = await sendGetOneAgentPolicy(AGENTLESS_POLICY_ID); + const isAgentlessAvailable = !error && data && data.item; + + if (isAgentlessAvailable) { + setAgentlessPolicy(data.item); + } + }; + + if (isAgentlessEnabled && isServerless) { + fetchAgentlessPolicy(); + } + }, [isAgentlessEnabled, isServerless]); + + const handleSetupTechnologyChange = useCallback( + (setupTechnology) => { + if (!isAgentlessEnabled || setupTechnology === selectedSetupTechnology) { + return; + } + + if (setupTechnology === SetupTechnology.AGENTLESS) { + if (agentlessPolicy) { + updateAgentPolicy(agentlessPolicy); + setSelectedPolicyTab(SelectedPolicyTab.EXISTING); + } + } else if (setupTechnology === SetupTechnology.AGENT_BASED) { + updateNewAgentPolicy(newAgentPolicy); + setSelectedPolicyTab(SelectedPolicyTab.NEW); + } + + setSelectedSetupTechnology(setupTechnology); + }, + [ + isAgentlessEnabled, + selectedSetupTechnology, + agentlessPolicy, + updateAgentPolicy, + setSelectedPolicyTab, + updateNewAgentPolicy, + newAgentPolicy, + ] + ); + + return { + handleSetupTechnologyChange, + agentlessPolicy, + selectedSetupTechnology, + }; +} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx index d0b82cf66e641..b5e29245c63cc 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx @@ -5,21 +5,21 @@ * 2.0. */ -import React, { useState, useEffect, useMemo, useCallback } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useRouteMatch } from 'react-router-dom'; import styled from 'styled-components'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { - EuiButtonEmpty, - EuiButton, - EuiSteps, EuiBottomBar, + EuiButton, + EuiButtonEmpty, + EuiCallOut, + EuiErrorBoundary, EuiFlexGroup, EuiFlexItem, EuiSpacer, - EuiErrorBoundary, - EuiCallOut, + EuiSteps, } from '@elastic/eui'; import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; @@ -31,35 +31,38 @@ import { import { useCancelAddPackagePolicy } from '../hooks'; import { isRootPrivilegesRequired, splitPkgKey } from '../../../../../../../common/services'; -import type { NewAgentPolicy } from '../../../../types'; -import { useConfig, sendGetAgentStatus, useGetPackageInfoByKeyQuery } from '../../../../hooks'; +import type { NewAgentPolicy, PackagePolicyEditExtensionComponentProps } from '../../../../types'; +import { SetupTechnology } from '../../../../types'; import { - Loading, + sendGetAgentStatus, + useConfig, + useGetPackageInfoByKeyQuery, + useUIExtension, +} from '../../../../hooks'; +import { + DevtoolsRequestFlyoutButton, Error as ErrorComponent, ExtensionWrapper, - DevtoolsRequestFlyoutButton, + Loading, } from '../../../../components'; import { agentPolicyFormValidation, ConfirmDeployAgentPolicyModal } from '../../components'; -import { useUIExtension } from '../../../../hooks'; -import type { PackagePolicyEditExtensionComponentProps } from '../../../../types'; import { pkgKeyFromPackageInfo } from '../../../../services'; import type { AddToPolicyParams, CreatePackagePolicyParams } from '../types'; -import { IntegrationBreadcrumb } from '../components'; - import { + IntegrationBreadcrumb, + SelectedPolicyTab, StepConfigurePackagePolicy, StepDefinePackagePolicy, - SelectedPolicyTab, StepSelectHosts, } from '../components'; import { generateNewAgentPolicyWithDefaults } from '../../../../../../../common/services/generate_new_agent_policy'; import { CreatePackagePolicySinglePageLayout, PostInstallAddAgentModal } from './components'; -import { useDevToolsRequest, useOnSubmit } from './hooks'; +import { useDevToolsRequest, useOnSubmit, useSetupTechnology } from './hooks'; import { PostInstallCloudFormationModal } from './components/post_install_cloud_formation_modal'; import { PostInstallGoogleCloudShellModal } from './components/post_install_google_cloud_shell_modal'; import { PostInstallAzureArmTemplateModal } from './components/post_install_azure_arm_template_modal'; @@ -293,6 +296,14 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ ); } + const { agentlessPolicy, handleSetupTechnologyChange, selectedSetupTechnology } = + useSetupTechnology({ + newAgentPolicy, + updateNewAgentPolicy, + updateAgentPolicy, + setSelectedPolicyTab, + }); + const replaceStepConfigurePackagePolicy = replaceDefineStepView && packageInfo?.name ? ( !isInitialized ? ( @@ -306,6 +317,8 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ onChange={handleExtensionViewOnChange} validationResults={validationResults} isEditPage={false} + handleSetupTechnologyChange={handleSetupTechnologyChange} + agentlessPolicy={agentlessPolicy} /> ) @@ -374,13 +387,16 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ 'data-test-subj': 'dataCollectionSetupStep', children: replaceStepConfigurePackagePolicy || stepConfigurePackagePolicy, }, - { + ]; + + if (selectedSetupTechnology !== SetupTechnology.AGENTLESS) { + steps.push({ title: i18n.translate('xpack.fleet.createPackagePolicy.stepSelectAgentPolicyTitle', { defaultMessage: 'Where to add this integration?', }), children: stepSelectAgentPolicy, - }, - ]; + }); + } // Display package error if there is one if (packageInfoError) { diff --git a/x-pack/plugins/fleet/public/index.ts b/x-pack/plugins/fleet/public/index.ts index 30ccf9c9c657d..1efc18a53e1e8 100644 --- a/x-pack/plugins/fleet/public/index.ts +++ b/x-pack/plugins/fleet/public/index.ts @@ -16,6 +16,7 @@ export const plugin = (initializerContext: PluginInitializerContext) => { }; export type { NewPackagePolicy, KibanaSavedObjectType } from './types'; +export { SetupTechnology } from './types'; export type { AgentDetailsReassignPolicyAction, AgentPolicyDetailsDeployAgentAction, diff --git a/x-pack/plugins/fleet/public/types/index.ts b/x-pack/plugins/fleet/public/types/index.ts index 63837dc809559..fe1c49af887d9 100644 --- a/x-pack/plugins/fleet/public/types/index.ts +++ b/x-pack/plugins/fleet/public/types/index.ts @@ -144,6 +144,7 @@ export { ElasticsearchAssetType, KibanaAssetType, InstallStatus, + SetupTechnology, } from '../../common/types'; export * from './intra_app_route_state'; diff --git a/x-pack/plugins/fleet/public/types/ui_extensions.ts b/x-pack/plugins/fleet/public/types/ui_extensions.ts index 53ae5322f0d9d..b5ae9dacf54bc 100644 --- a/x-pack/plugins/fleet/public/types/ui_extensions.ts +++ b/x-pack/plugins/fleet/public/types/ui_extensions.ts @@ -36,6 +36,8 @@ export type PackagePolicyReplaceDefineStepExtensionComponentProps = ( validationResults?: PackagePolicyValidationResults; agentPolicy?: AgentPolicy; packageInfo: PackageInfo; + agentlessPolicy?: AgentPolicy; + handleSetupTechnologyChange?: (setupTechnology: string) => void; }; /** From 754c298d12f9c51334a35d0c8b0681da0126276e Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Thu, 7 Dec 2023 10:08:45 +0100 Subject: [PATCH 3/4] [EBT] fix browser-side elasticsearch context schema (#172676) ## Summary The `cluster_build_flavor` was propagated to the browser-side and then used in the context, but without being explicitly defined in the schema. this PR fixes it by properly adding the field. --- .../core-analytics-browser-internal/src/analytics_service.ts | 4 ++++ .../core-injected-metadata-common-internal/src/types.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts b/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts index 60656e9dfd1cb..fc394702eadfa 100644 --- a/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts +++ b/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts @@ -184,6 +184,10 @@ export class AnalyticsService { type: 'keyword', _meta: { description: 'The Cluster version', optional: true }, }, + cluster_build_flavor: { + type: 'keyword', + _meta: { description: 'The Cluster build flavor', optional: true }, + }, }, }); } diff --git a/packages/core/injected-metadata/core-injected-metadata-common-internal/src/types.ts b/packages/core/injected-metadata/core-injected-metadata-common-internal/src/types.ts index dd9d6bced5c98..01b46679c7452 100644 --- a/packages/core/injected-metadata/core-injected-metadata-common-internal/src/types.ts +++ b/packages/core/injected-metadata/core-injected-metadata-common-internal/src/types.ts @@ -16,6 +16,7 @@ export interface InjectedMetadataClusterInfo { cluster_uuid?: string; cluster_name?: string; cluster_version?: string; + cluster_build_flavor?: string; } /** @internal */ From ef5305d47f3daaefe6f2bee858d94770a4a86f71 Mon Sep 17 00:00:00 2001 From: Jordan <51442161+JordanSh@users.noreply.github.com> Date: Thu, 7 Dec 2023 11:12:51 +0200 Subject: [PATCH 4/4] [Cloud Security] Remove manual-manual from azure integration (#172669) --- .../cloud_security_posture/common/types.ts | 4 +-- .../azure_credentials_form.tsx | 12 ------- .../get_azure_credentials_form_options.tsx | 35 ++++++++----------- .../azure_credentials_form/hooks.ts | 7 ++-- .../policy_template_form.test.tsx | 1 + .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 8 files changed, 20 insertions(+), 42 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/common/types.ts b/x-pack/plugins/cloud_security_posture/common/types.ts index aa25c70eb247d..fc4391b5fbf76 100644 --- a/x-pack/plugins/cloud_security_posture/common/types.ts +++ b/x-pack/plugins/cloud_security_posture/common/types.ts @@ -32,11 +32,11 @@ export type GcpCredentialsTypeFieldMap = { export type AzureCredentialsType = | 'arm_template' + | 'manual' // TODO: remove for stack version 8.13 | 'service_principal_with_client_secret' | 'service_principal_with_client_certificate' | 'service_principal_with_client_username_and_password' - | 'managed_identity' - | 'manual'; + | 'managed_identity'; export type AzureCredentialsTypeFieldMap = { [key in AzureCredentialsType]: string[]; diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/azure_credentials_form.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/azure_credentials_form.tsx index ab8770b20f0cf..e941d81112d0c 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/azure_credentials_form.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/azure_credentials_form.tsx @@ -248,18 +248,6 @@ const TemporaryManualSetup = ({ integrationLink }: { integrationLink: string }) const AZURE_MINIMUM_PACKAGE_VERSION = '1.6.0'; const AZURE_MANUAL_FIELDS_PACKAGE_VERSION = '1.7.0'; -export const getDefaultAzureManualCredentialType = (packageInfo: PackageInfo) => { - const packageSemanticVersion = semverValid(packageInfo.version); - const cleanPackageVersion = semverCoerce(packageSemanticVersion) || ''; - - const isPackageVersionValidForManualFields = !semverLt( - cleanPackageVersion, - AZURE_MANUAL_FIELDS_PACKAGE_VERSION - ); - - return isPackageVersionValidForManualFields ? 'managed_identity' : 'manual'; -}; - const AzureInputVarFields = ({ fields, onChange, diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/get_azure_credentials_form_options.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/get_azure_credentials_form_options.tsx index 455fe9352ba00..fb28255a08985 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/get_azure_credentials_form_options.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/get_azure_credentials_form_options.tsx @@ -26,12 +26,15 @@ export const getAzureCredentialsFormManualOptions = (): Array<{ value: AzureCredentialsType; text: string; }> => { - return Object.entries(getAzureCredentialsFormOptions()) - .map(([key, value]) => ({ - value: key as AzureCredentialsType, - text: value.label, - })) - .filter(({ value }) => value !== 'arm_template'); + return ( + Object.entries(getAzureCredentialsFormOptions()) + .map(([key, value]) => ({ + value: key as AzureCredentialsType, + text: value.label, + })) + // TODO: remove 'manual' for stack version 8.13 + .filter(({ value }) => value !== 'arm_template' && value !== 'manual') + ); }; export const getInputVarsFields = (input: NewPackagePolicyInput, fields: AzureCredentialsFields) => @@ -75,6 +78,12 @@ export const getAzureCredentialsFormOptions = (): AzureOptions => ({ info: [], fields: {}, }, + // TODO: remove for stack version 8.13 + manual: { + label: 'Manual', + info: [], + fields: {}, + }, service_principal_with_client_secret: { label: i18n.translate('xpack.csp.azureIntegration.servicePrincipalWithClientSecretLabel', { defaultMessage: 'Service principal with Client Secret', @@ -131,18 +140,4 @@ export const getAzureCredentialsFormOptions = (): AzureOptions => ({ }, }, }, - manual: { - label: i18n.translate('xpack.csp.azureIntegration.credentialType.manualLabel', { - defaultMessage: 'Manual', - }), - info: ( - - - - ), - fields: {}, - }, }); diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/hooks.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/hooks.ts index b68828be58117..a229c1a1486f0 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/hooks.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/hooks.ts @@ -7,10 +7,7 @@ import { useEffect, useRef } from 'react'; import { NewPackagePolicy, PackageInfo } from '@kbn/fleet-plugin/common'; -import { - AZURE_ARM_TEMPLATE_CREDENTIAL_TYPE, - getDefaultAzureManualCredentialType, -} from './azure_credentials_form'; +import { AZURE_ARM_TEMPLATE_CREDENTIAL_TYPE } from './azure_credentials_form'; import { cspIntegrationDocsNavigation } from '../../../common/navigation/constants'; import { getArmTemplateUrlFromCspmPackage, @@ -151,7 +148,7 @@ export const useAzureCredentialsForm = ({ setupFormat, }); - const defaultAzureManualCredentialType = getDefaultAzureManualCredentialType(packageInfo); + const defaultAzureManualCredentialType = 'managed_identity'; const onSetupFormatChange = (newSetupFormat: SetupFormat) => { if (newSetupFormat === AZURE_ARM_TEMPLATE_CREDENTIAL_TYPE) { diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx index d0c1f4d454b4f..5764b5af44357 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx @@ -1330,6 +1330,7 @@ describe('', () => { ).toBeInTheDocument(); }); + // TODO: remove for stack version 8.13 it(`doesnt render ${CLOUDBEAT_AZURE} Manual fields when version is not at least version 1.7.0`, () => { let policy = getMockPolicyAzure(); policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, { diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 4149395492ce6..330edcd2e2776 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -12129,7 +12129,6 @@ "xpack.csp.azureIntegration.armTemplateSetupStep.notSupported": "Le modèle ARM n'est pas compatible avec la version actuelle de l'intégration. Veuillez passer à la version la plus récente de votre intégration pour utiliser le modèle ARM", "xpack.csp.azureIntegration.armTemplateSetupStep.save": "Cliquez sur le bouton \"Enregistrer et continuer\" en bas à droite de cette page.", "xpack.csp.azureIntegration.azureNotSupportedMessage": "CIS Azure n'est pas compatible avec la version actuelle de l'intégration. Veuillez passer à la version la plus récente de votre intégration pour utiliser CIS Azure", - "xpack.csp.azureIntegration.credentialType.manualLabel": "Manuel", "xpack.csp.azureIntegration.documentationLinkText": "documentation", "xpack.csp.azureIntegration.gettingStarted.setupInfoContentLink": "Guide de premiers pas", "xpack.csp.azureIntegration.setupFormatOptions.manual": "Manuel", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 107a0c7e929b6..364c17cad6690 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -12143,7 +12143,6 @@ "xpack.csp.azureIntegration.armTemplateSetupStep.notSupported": "ARMテンプレートは現在の統合バージョンではサポートされていません。ARMテンプレートを使用するには、統合を最新バージョンにアップグレードしてください", "xpack.csp.azureIntegration.armTemplateSetupStep.save": "このページの右下にある\"保存して続行\"ボタンをクリックしてください。", "xpack.csp.azureIntegration.azureNotSupportedMessage": "CIS Azureは現在の統合バージョンではサポートされていません。CIS Azureを使用するには、統合を最新バージョンにアップグレードしてください", - "xpack.csp.azureIntegration.credentialType.manualLabel": "手動", "xpack.csp.azureIntegration.documentationLinkText": "ドキュメンテーション", "xpack.csp.azureIntegration.gettingStarted.setupInfoContentLink": "入門ガイド", "xpack.csp.azureIntegration.setupFormatOptions.manual": "手動", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 0ed4a01b5d034..70c282560d63e 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -12143,7 +12143,6 @@ "xpack.csp.azureIntegration.armTemplateSetupStep.notSupported": "当前版本的集成不支持 ARM 模板,请将集成升级到最新版本以使用 ARM 模板", "xpack.csp.azureIntegration.armTemplateSetupStep.save": "单击此页面底部右侧的“保存并继续”按钮。", "xpack.csp.azureIntegration.azureNotSupportedMessage": "当前版本的集成不支持 CIS Azure,请将集成升级到最新版本以使用 CIS Azure", - "xpack.csp.azureIntegration.credentialType.manualLabel": "手动", "xpack.csp.azureIntegration.documentationLinkText": "文档", "xpack.csp.azureIntegration.gettingStarted.setupInfoContentLink": "入门指南", "xpack.csp.azureIntegration.setupFormatOptions.manual": "手动",