Skip to content

Commit

Permalink
[8.x] [Defend Workflows][Reusable integrations] Handling resuable int…
Browse files Browse the repository at this point in the history
…egrations on endpoint onboarding page (#193518) (#194617)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Defend Workflows][Reusable integrations] Handling resuable
integrations on endpoint onboarding page
(#193518)](#193518)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Gergő
Ábrahám","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-10-01T16:54:43Z","message":"[Defend
Workflows][Reusable integrations] Handling resuable integrations on
endpoint onboarding page (#193518)\n\n## Summary\r\n\r\nDuring
onboarding on the Endpoint list page, if the user already created\r\nat
least one Elastic Defend integration, we show this screen
(original):\r\n<img width=\"400\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/98f04002-7c18-48bf-8b29-a4ad6113385c\">\r\n\r\nDue
to the new enterprise level feature added by Fleet team, the\r\nreusable
integrations, now an integration policy can be assigned **zero,\r\none
or more agent policies**, and this PR's goal is to update
this\r\nonboarding screen to tackle these changes.\r\n\r\n### One
integration is added to more than one Agent Policies\r\nWhen
creating/editing an integration, it can be added to more than
one\r\nAgent Policies:\r\n\r\n<img width=\"600\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/f0982e28-11b0-4aef-a059-6c952e0e33b7\">\r\n\r\n####
✅ Solution for usecase\r\nTo be able to select where to enroll an Agent,
now they are listed as\r\n`Package policy - Agent policy` pairs.\r\n<img
width=\"600\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/c82d70ed-5b87-43b5-ab16-3c4549373b32\">\r\n\r\n###
Some integrations are not added to an Agent Policy\r\n<img width=\"400\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/108ccd78-d019-42ca-a92a-905344172d09\">\r\n\r\n####
✅ Solution for usecase\r\nA new callout is added to indicate to the user
that there are some\r\nintegrations that cannot be deployed to an
Agent.\r\n\r\n<img width=\"600\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/3bedc56b-70a3-4f4f-9881-e91ae458cadf\">\r\n\r\nClicking
on the Integrations opens their editing page in a new tab.\r\nClickin on
the 'Elastic Defend Integration policies' opens the
Defend\r\nintegration's policies tab in a new browser tab.\r\n\r\n###
None of the integrations are added to an Agent Policy\r\n<img
width=\"300\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/39fd2efc-2a96-4109-9311-b666bd44ca1f\">\r\n\r\n####
✅ Solution for usecase\r\nAnother 'warning' callout is displayed
indicating that there are no\r\nusable integrations. This, combined with
the other callout hopefully\r\nhelp the user to go forward.\r\n\r\n<img
width=\"600\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/78efc1ea-dd3e-4aff-bd67-b1e37a2508e1\">\r\n\r\n\r\n###
RBAC\r\nIn case the user doesn't hold the required privileges, the same
screen\r\nis displayed as when there are no hosts and no policies, or
there are\r\npolicies but no hosts. Just as before.\r\n<img
width=\"600\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/814f460d-7e17-49a7-8337-9cf1f8a8f0ef\">\r\n\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] Any UI
touched in this PR is usable by keyboard only (learn more\r\nabout
[keyboard accessibility](https://webaim.org/techniques/keyboard/))\r\n-
[x] Any UI touched in this PR does not create any new axe
failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[x] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n\r\n---------\r\n\r\nCo-authored-by:
Elastic Machine
<[email protected]>\r\nCo-authored-by: Joe Peeples
<[email protected]>","sha":"8eceb0db4d4edb0da52564ac082859abfc6ed6e7","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","Team:Defend
Workflows","v8.16.0","backport:version"],"title":"[Defend
Workflows][Reusable integrations] Handling resuable integrations on
endpoint onboarding
page","number":193518,"url":"https://github.com/elastic/kibana/pull/193518","mergeCommit":{"message":"[Defend
Workflows][Reusable integrations] Handling resuable integrations on
endpoint onboarding page (#193518)\n\n## Summary\r\n\r\nDuring
onboarding on the Endpoint list page, if the user already created\r\nat
least one Elastic Defend integration, we show this screen
(original):\r\n<img width=\"400\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/98f04002-7c18-48bf-8b29-a4ad6113385c\">\r\n\r\nDue
to the new enterprise level feature added by Fleet team, the\r\nreusable
integrations, now an integration policy can be assigned **zero,\r\none
or more agent policies**, and this PR's goal is to update
this\r\nonboarding screen to tackle these changes.\r\n\r\n### One
integration is added to more than one Agent Policies\r\nWhen
creating/editing an integration, it can be added to more than
one\r\nAgent Policies:\r\n\r\n<img width=\"600\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/f0982e28-11b0-4aef-a059-6c952e0e33b7\">\r\n\r\n####
✅ Solution for usecase\r\nTo be able to select where to enroll an Agent,
now they are listed as\r\n`Package policy - Agent policy` pairs.\r\n<img
width=\"600\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/c82d70ed-5b87-43b5-ab16-3c4549373b32\">\r\n\r\n###
Some integrations are not added to an Agent Policy\r\n<img width=\"400\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/108ccd78-d019-42ca-a92a-905344172d09\">\r\n\r\n####
✅ Solution for usecase\r\nA new callout is added to indicate to the user
that there are some\r\nintegrations that cannot be deployed to an
Agent.\r\n\r\n<img width=\"600\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/3bedc56b-70a3-4f4f-9881-e91ae458cadf\">\r\n\r\nClicking
on the Integrations opens their editing page in a new tab.\r\nClickin on
the 'Elastic Defend Integration policies' opens the
Defend\r\nintegration's policies tab in a new browser tab.\r\n\r\n###
None of the integrations are added to an Agent Policy\r\n<img
width=\"300\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/39fd2efc-2a96-4109-9311-b666bd44ca1f\">\r\n\r\n####
✅ Solution for usecase\r\nAnother 'warning' callout is displayed
indicating that there are no\r\nusable integrations. This, combined with
the other callout hopefully\r\nhelp the user to go forward.\r\n\r\n<img
width=\"600\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/78efc1ea-dd3e-4aff-bd67-b1e37a2508e1\">\r\n\r\n\r\n###
RBAC\r\nIn case the user doesn't hold the required privileges, the same
screen\r\nis displayed as when there are no hosts and no policies, or
there are\r\npolicies but no hosts. Just as before.\r\n<img
width=\"600\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/814f460d-7e17-49a7-8337-9cf1f8a8f0ef\">\r\n\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] Any UI
touched in this PR is usable by keyboard only (learn more\r\nabout
[keyboard accessibility](https://webaim.org/techniques/keyboard/))\r\n-
[x] Any UI touched in this PR does not create any new axe
failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[x] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n\r\n---------\r\n\r\nCo-authored-by:
Elastic Machine
<[email protected]>\r\nCo-authored-by: Joe Peeples
<[email protected]>","sha":"8eceb0db4d4edb0da52564ac082859abfc6ed6e7"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/193518","number":193518,"mergeCommit":{"message":"[Defend
Workflows][Reusable integrations] Handling resuable integrations on
endpoint onboarding page (#193518)\n\n## Summary\r\n\r\nDuring
onboarding on the Endpoint list page, if the user already created\r\nat
least one Elastic Defend integration, we show this screen
(original):\r\n<img width=\"400\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/98f04002-7c18-48bf-8b29-a4ad6113385c\">\r\n\r\nDue
to the new enterprise level feature added by Fleet team, the\r\nreusable
integrations, now an integration policy can be assigned **zero,\r\none
or more agent policies**, and this PR's goal is to update
this\r\nonboarding screen to tackle these changes.\r\n\r\n### One
integration is added to more than one Agent Policies\r\nWhen
creating/editing an integration, it can be added to more than
one\r\nAgent Policies:\r\n\r\n<img width=\"600\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/f0982e28-11b0-4aef-a059-6c952e0e33b7\">\r\n\r\n####
✅ Solution for usecase\r\nTo be able to select where to enroll an Agent,
now they are listed as\r\n`Package policy - Agent policy` pairs.\r\n<img
width=\"600\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/c82d70ed-5b87-43b5-ab16-3c4549373b32\">\r\n\r\n###
Some integrations are not added to an Agent Policy\r\n<img width=\"400\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/108ccd78-d019-42ca-a92a-905344172d09\">\r\n\r\n####
✅ Solution for usecase\r\nA new callout is added to indicate to the user
that there are some\r\nintegrations that cannot be deployed to an
Agent.\r\n\r\n<img width=\"600\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/3bedc56b-70a3-4f4f-9881-e91ae458cadf\">\r\n\r\nClicking
on the Integrations opens their editing page in a new tab.\r\nClickin on
the 'Elastic Defend Integration policies' opens the
Defend\r\nintegration's policies tab in a new browser tab.\r\n\r\n###
None of the integrations are added to an Agent Policy\r\n<img
width=\"300\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/39fd2efc-2a96-4109-9311-b666bd44ca1f\">\r\n\r\n####
✅ Solution for usecase\r\nAnother 'warning' callout is displayed
indicating that there are no\r\nusable integrations. This, combined with
the other callout hopefully\r\nhelp the user to go forward.\r\n\r\n<img
width=\"600\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/78efc1ea-dd3e-4aff-bd67-b1e37a2508e1\">\r\n\r\n\r\n###
RBAC\r\nIn case the user doesn't hold the required privileges, the same
screen\r\nis displayed as when there are no hosts and no policies, or
there are\r\npolicies but no hosts. Just as before.\r\n<img
width=\"600\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/814f460d-7e17-49a7-8337-9cf1f8a8f0ef\">\r\n\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] Any UI
touched in this PR is usable by keyboard only (learn more\r\nabout
[keyboard accessibility](https://webaim.org/techniques/keyboard/))\r\n-
[x] Any UI touched in this PR does not create any new axe
failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[x] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n\r\n---------\r\n\r\nCo-authored-by:
Elastic Machine
<[email protected]>\r\nCo-authored-by: Joe Peeples
<[email protected]>","sha":"8eceb0db4d4edb0da52564ac082859abfc6ed6e7"}},{"branch":"8.x","label":"v8.16.0","branchLabelMappingKey":"^v8.16.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Gergő Ábrahám <[email protected]>
  • Loading branch information
kibanamachine and gergoabraham authored Oct 1, 2024
1 parent cf8e693 commit c601fdf
Show file tree
Hide file tree
Showing 11 changed files with 672 additions and 300 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type PartialPackagePolicy = Partial<Omit<PackagePolicy, 'inputs'>> & {
inputs?: PackagePolicy['inputs'];
};

type PartialEndpointPolicyData = Partial<Omit<PolicyData, 'inputs'>> & {
export type PartialEndpointPolicyData = Partial<Omit<PolicyData, 'inputs'>> & {
inputs?: PolicyData['inputs'];
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
import { firstNonNullValue } from './models/ecs_safety_helpers';
import type { EventOptions } from './types/generator';
import { BaseDataGenerator } from './data_generators/base_data_generator';
import type { PartialEndpointPolicyData } from './data_generators/fleet_package_policy_generator';
import { FleetPackagePolicyGenerator } from './data_generators/fleet_package_policy_generator';

export type Event = AlertEvent | SafeEndpointEvent;
Expand Down Expand Up @@ -1581,8 +1582,14 @@ export class EndpointDocGenerator extends BaseDataGenerator {
/**
* Generates a Fleet `package policy` that includes the Endpoint Policy data
*/
public generatePolicyPackagePolicy(seed: string = 'seed'): PolicyData {
return new FleetPackagePolicyGenerator(seed).generateEndpointPackagePolicy();
public generatePolicyPackagePolicy({
seed,
overrides,
}: {
seed?: string;
overrides?: PartialEndpointPolicyData;
} = {}): PolicyData {
return new FleetPackagePolicyGenerator(seed).generateEndpointPackagePolicy(overrides);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,16 @@ import {
EuiLoadingSpinner,
EuiLink,
EuiSkeletonText,
EuiCallOut,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { INTEGRATIONS_PLUGIN_ID } from '@kbn/fleet-plugin/common';
import { pagePathGetters } from '@kbn/fleet-plugin/public';
import type { ImmutableArray, PolicyData } from '../../../common/endpoint/types';
import { useUserPrivileges } from '../../common/components/user_privileges';
import onboardingLogo from '../images/security_administration_onboarding.svg';
import { useKibana } from '../../common/lib/kibana';
import { useAppUrl, useKibana } from '../../common/lib/kibana';

const TEXT_ALIGN_CENTER: CSSProperties = Object.freeze({
textAlign: 'center',
Expand Down Expand Up @@ -103,12 +107,12 @@ const PolicyEmptyState = React.memo<{
{policyEntryPoint ? (
<FormattedMessage
id="xpack.securitySolution.endpoint.policyList.onboardingSectionTwo.fromPolicyPage"
defaultMessage="From this page, you’ll be able to view and manage the Elastic Defend Integration policies in your environment running Elastic Defend."
defaultMessage="From this page, you can view and manage the Elastic Defend integration policies in your environment running Elastic Defend."
/>
) : (
<FormattedMessage
id="xpack.securitySolution.endpoint.policyList.onboardingSectionTwo.fromEndpointPage"
defaultMessage="From this page, you’ll be able to view and manage the hosts in your environment running Elastic Defend."
defaultMessage="From this page, you can view and manage the hosts in your environment running Elastic Defend."
/>
)}
</EuiText>
Expand Down Expand Up @@ -170,107 +174,216 @@ const EndpointsEmptyState = React.memo<{
actionDisabled: boolean;
handleSelectableOnChange: (o: EuiSelectableProps['options']) => void;
selectionOptions: EuiSelectableProps['options'];
}>(({ loading, onActionClick, actionDisabled, handleSelectableOnChange, selectionOptions }) => {
const policySteps = useMemo(
() => [
{
title: i18n.translate('xpack.securitySolution.endpoint.list.stepOneTitle', {
defaultMessage: 'Select the integration you want to use',
}),
children: (
policyItems: ImmutableArray<PolicyData>;
}>(
({
loading,
onActionClick,
actionDisabled,
handleSelectableOnChange,
selectionOptions,
policyItems,
}) => {
const { getAppUrl } = useAppUrl();
const policyItemsWithoutAgentPolicy = useMemo(
() => policyItems.filter((policy) => !policy.policy_ids.length),
[policyItems]
);

const policiesNotAddedToAgentPolicyCallout = useMemo(
() =>
!!policyItemsWithoutAgentPolicy.length && (
<>
<EuiText color="subdued" size="m" grow={false}>
<FormattedMessage
id="xpack.securitySolution.endpoint.list.stepOne"
defaultMessage="Select from existing integrations. This can be changed later."
/>
</EuiText>
<EuiSpacer size="xxl" />
<EuiSelectable
options={selectionOptions}
singleSelection="always"
isLoading={loading}
height={100}
listProps={{ bordered: true, singleSelection: true }}
onChange={handleSelectableOnChange}
data-test-subj="onboardingPolicySelect"
<EuiSpacer size="xl" />
<EuiCallOut
color="primary"
iconType="iInCircle"
title={i18n.translate(
'xpack.securitySolution.endpoint.list.notAddedIntegrations.title',
{
defaultMessage: 'Integrations not added to an Agent policy',
}
)}
data-test-subj="integrationsNotAddedToAgentPolicyCallout"
>
{(list) => {
return loading ? (
<EuiSelectableMessage>
<FormattedMessage
id="xpack.securitySolution.endpoint.list.loadingPolicies"
defaultMessage="Loading integrations"
/>
</EuiSelectableMessage>
) : selectionOptions.length ? (
list
) : (
<FormattedMessage
id="xpack.securitySolution.endpoint.list.noPolicies"
defaultMessage="There are no integrations."
/>
);
}}
</EuiSelectable>
<EuiSpacer size="s" />

<EuiText size="s" color="subdued">
<FormattedMessage
id="xpack.securitySolution.endpoint.list.notAddedIntegrations.description"
defaultMessage="The following Elastic Defend integrations aren't added to an Agent policy, so they can't be deployed to an Agent. Click on an integration to edit it, and add it to an Agent policy:"
/>

<EuiSpacer size="s" />

<ul>
{policyItemsWithoutAgentPolicy.map((policyItem) => (
<li key={policyItem.id}>
<EuiLink
target="_blank"
href={getAppUrl({
appId: INTEGRATIONS_PLUGIN_ID,
path: pagePathGetters.integration_policy_edit({
packagePolicyId: policyItem.id,
})[1],
})}
data-test-subj="integrationWithoutAgentPolicyListItem"
>
{policyItem.name}
</EuiLink>
</li>
))}
</ul>

<FormattedMessage
id="xpack.securitySolution.endpoint.list.notAddedIntegrations.visitIntegrations"
defaultMessage="You can also view a list of all {integrationPolicies}."
values={{
integrationPolicies: (
<EuiLink
target="_blank"
href={getAppUrl({
appId: INTEGRATIONS_PLUGIN_ID,
path: pagePathGetters.integration_details_policies({
pkgkey: 'endpoint',
})[1],
})}
>
<FormattedMessage
id="xpack.securitySolution.endpoint.list.notAddedIntegrations.integrationPolicies"
defaultMessage="Elastic Defend integration policies"
/>
</EuiLink>
),
}}
/>
</EuiText>
</EuiCallOut>
</>
),
},
{
title: i18n.translate('xpack.securitySolution.endpoint.list.stepTwoTitle', {
defaultMessage: 'Enroll your agents enabled with Elastic Defend through Fleet',
}),
status: actionDisabled ? 'disabled' : '',
children: (
<EuiFlexGroup alignItems="center">
<EuiFlexItem>
[getAppUrl, policyItemsWithoutAgentPolicy]
);

const policySteps = useMemo(
() => [
{
title: i18n.translate('xpack.securitySolution.endpoint.list.stepOneTitle', {
defaultMessage: 'Select the integration you want to use',
}),
children: (
<>
<EuiText color="subdued" size="m" grow={false}>
<FormattedMessage
id="xpack.securitySolution.endpoint.list.stepTwo"
defaultMessage="You’ll be provided with the necessary commands to get started."
id="xpack.securitySolution.endpoint.list.stepOne"
defaultMessage="Select from existing integrations. This can be changed later."
/>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
fill
onClick={onActionClick}
isDisabled={actionDisabled}
data-test-subj="onboardingStartButton"
<EuiSpacer size="xxl" />
<EuiSelectable
options={selectionOptions}
singleSelection="always"
isLoading={loading}
listProps={{ bordered: true, singleSelection: true }}
onChange={handleSelectableOnChange}
data-test-subj="onboardingPolicySelect"
>
<FormattedMessage
id="xpack.securitySolution.endpoint.policyList.emptyCreateNewButton"
defaultMessage="Enroll Agent"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
),
},
],
[selectionOptions, handleSelectableOnChange, loading, actionDisabled, onActionClick]
);
{(list) => {
if (loading) {
return (
<EuiSelectableMessage>
<FormattedMessage
id="xpack.securitySolution.endpoint.list.loadingPolicies"
defaultMessage="Loading integrations"
/>
</EuiSelectableMessage>
);
}

return (
<ManagementEmptyState
loading={loading}
dataTestSubj="emptyHostsTable"
steps={policySteps}
headerComponent={
<FormattedMessage
id="xpack.securitySolution.endpoint.list.noEndpointsPrompt"
defaultMessage="Next step: Enroll an Agent with Elastic Defend"
/>
}
bodyComponent={
<FormattedMessage
id="xpack.securitySolution.endpoint.list.noEndpointsInstructions"
defaultMessage="You’ve added the Elastic Defend integration. Now enroll your agents using the steps below."
/>
}
/>
);
});
if (!selectionOptions.length) {
return (
<EuiCallOut
color="warning"
data-test-subj="noIntegrationsAddedToAgentPoliciesCallout"
>
<FormattedMessage
id="xpack.securitySolution.endpoint.list.noPoliciesAssignedToAgentPolicies"
defaultMessage="There are no Elastic Defend integrations added to Agent policies. To deploy Elastic Defend, add it to an Agent policy."
/>
</EuiCallOut>
);
}

return list;
}}
</EuiSelectable>

{policiesNotAddedToAgentPolicyCallout}
</>
),
},
{
title: i18n.translate('xpack.securitySolution.endpoint.list.stepTwoTitle', {
defaultMessage: 'Enroll your agents enabled with Elastic Defend through Fleet',
}),
status: actionDisabled ? 'disabled' : '',
children: (
<EuiFlexGroup alignItems="center">
<EuiFlexItem>
<EuiText color="subdued" size="m" grow={false}>
<FormattedMessage
id="xpack.securitySolution.endpoint.list.stepTwo"
defaultMessage="You'll be provided with the necessary commands to get started."
/>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
fill
onClick={onActionClick}
isDisabled={actionDisabled}
data-test-subj="onboardingStartButton"
>
<FormattedMessage
id="xpack.securitySolution.endpoint.policyList.emptyCreateNewButton"
defaultMessage="Enroll Agent"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
),
},
],
[
selectionOptions,
loading,
handleSelectableOnChange,
policiesNotAddedToAgentPolicyCallout,
actionDisabled,
onActionClick,
]
);

return (
<ManagementEmptyState
loading={loading}
dataTestSubj="emptyHostsTable"
steps={policySteps}
headerComponent={
<FormattedMessage
id="xpack.securitySolution.endpoint.list.noEndpointsPrompt"
defaultMessage="Next step: Enroll an Agent with Elastic Defend"
/>
}
bodyComponent={
<FormattedMessage
id="xpack.securitySolution.endpoint.list.noEndpointsInstructions"
defaultMessage="You've added the Elastic Defend integration. Now enroll your agents using the steps below."
/>
}
/>
);
}
);

const ManagementEmptyState = React.memo<{
loading: boolean;
Expand All @@ -284,7 +397,11 @@ const ManagementEmptyState = React.memo<{
{loading ? (
<EuiFlexGroup alignItems="center" justifyContent="center">
<EuiFlexItem grow={false}>
<EuiLoadingSpinner size="xl" className="essentialAnimation" />
<EuiLoadingSpinner
size="xl"
className="essentialAnimation"
data-test-subj="management-empty-state-loading-spinner"
/>
</EuiFlexItem>
</EuiFlexGroup>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,6 @@ const getAgentAndPoliciesForEndpointsList = async (
return;
}

// We use the Agent Policy API here, instead of the Package Policy, because we can't use
// filter by ID of the Saved Object. Agent Policy, however, keeps a reference (array) of
// Package Ids that it uses, thus if a reference exists there, then the package policy (policy)
// exists.
const policiesFound = (
await sendBulkGetPackagePolicies(http, policyIdsToCheck)
).items.reduce<PolicyIds>(
Expand Down
Loading

0 comments on commit c601fdf

Please sign in to comment.