diff --git a/x-pack/plugins/fleet/common/services/index.ts b/x-pack/plugins/fleet/common/services/index.ts
index 663cd27deab73..badaff8cb29d3 100644
--- a/x-pack/plugins/fleet/common/services/index.ts
+++ b/x-pack/plugins/fleet/common/services/index.ts
@@ -7,6 +7,7 @@
export * from './routes';
export * as AgentStatusKueryHelper from './agent_status';
+export * from './package_helpers';
export {
packageToPackagePolicyInputs,
packageToPackagePolicy,
diff --git a/x-pack/plugins/fleet/common/services/package_helpers.test.ts b/x-pack/plugins/fleet/common/services/package_helpers.test.ts
new file mode 100644
index 0000000000000..71d3a9018ed5e
--- /dev/null
+++ b/x-pack/plugins/fleet/common/services/package_helpers.test.ts
@@ -0,0 +1,40 @@
+/*
+ * 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 { isRootPrivilegesRequired } from './package_helpers';
+
+describe('isRootPrivilegesRequired', () => {
+ it('should return true if root privileges is required at root level', () => {
+ const res = isRootPrivilegesRequired({
+ agent: {
+ privileges: {
+ root: true,
+ },
+ },
+ } as any);
+ expect(res).toBe(true);
+ });
+ it('should return true if root privileges is required at datastreams', () => {
+ const res = isRootPrivilegesRequired({
+ data_streams: [
+ {
+ agent: {
+ privileges: { root: true },
+ },
+ },
+ ],
+ } as any);
+ expect(res).toBe(true);
+ });
+
+ it('should return false if root privileges is not required', () => {
+ const res = isRootPrivilegesRequired({
+ data_streams: [],
+ } as any);
+ expect(res).toBe(false);
+ });
+});
diff --git a/x-pack/plugins/fleet/common/services/package_helpers.ts b/x-pack/plugins/fleet/common/services/package_helpers.ts
new file mode 100644
index 0000000000000..0282d218cec39
--- /dev/null
+++ b/x-pack/plugins/fleet/common/services/package_helpers.ts
@@ -0,0 +1,18 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import type { PackageInfo } from '../types';
+
+/**
+ * Return true if a package need Elastic Agent to be run as root/administrator
+ */
+export function isRootPrivilegesRequired(packageInfo: PackageInfo) {
+ return (
+ packageInfo.agent?.privileges?.root ||
+ packageInfo.data_streams?.some((d) => d.agent?.privileges?.root)
+ );
+}
diff --git a/x-pack/plugins/fleet/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts
index d8400a8a61b9b..c4d4e9c763766 100644
--- a/x-pack/plugins/fleet/common/types/models/epm.ts
+++ b/x-pack/plugins/fleet/common/types/models/epm.ts
@@ -337,6 +337,7 @@ export enum RegistryDataStreamKeys {
dataset_is_prefix = 'dataset_is_prefix',
routing_rules = 'routing_rules',
lifecycle = 'lifecycle',
+ agent = 'agent',
}
export interface RegistryDataStream {
@@ -355,6 +356,12 @@ export interface RegistryDataStream {
[RegistryDataStreamKeys.dataset_is_prefix]?: boolean;
[RegistryDataStreamKeys.routing_rules]?: RegistryDataStreamRoutingRules[];
[RegistryDataStreamKeys.lifecycle]?: RegistryDataStreamLifecycle;
+ [RegistryDataStreamKeys.lifecycle]?: RegistryDataStreamLifecycle;
+ [RegistryDataStreamKeys.agent]?: RegistryAgent;
+}
+
+export interface RegistryAgent {
+ privileges?: { root?: boolean };
}
export interface RegistryElasticsearch {
diff --git a/x-pack/plugins/fleet/common/types/models/package_spec.ts b/x-pack/plugins/fleet/common/types/models/package_spec.ts
index d372defd72c0e..60bc051af04fc 100644
--- a/x-pack/plugins/fleet/common/types/models/package_spec.ts
+++ b/x-pack/plugins/fleet/common/types/models/package_spec.ts
@@ -31,6 +31,9 @@ export interface PackageSpecManifest {
RegistryElasticsearch,
'index_template.settings' | 'index_template.mappings' | 'index_template.data_stream'
>;
+ agent?: {
+ privileges?: { root?: boolean };
+ };
asset_tags?: PackageSpecTags[];
}
export interface PackageSpecTags {
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 f4e46650f2049..d0b82cf66e641 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
@@ -19,6 +19,7 @@ import {
EuiFlexItem,
EuiSpacer,
EuiErrorBoundary,
+ EuiCallOut,
} from '@elastic/eui';
import type { EuiStepProps } from '@elastic/eui/src/components/steps/step';
@@ -29,7 +30,7 @@ import {
import { useCancelAddPackagePolicy } from '../hooks';
-import { splitPkgKey } from '../../../../../../../common/services';
+import { isRootPrivilegesRequired, splitPkgKey } from '../../../../../../../common/services';
import type { NewAgentPolicy } from '../../../../types';
import { useConfig, sendGetAgentStatus, useGetPackageInfoByKeyQuery } from '../../../../hooks';
import {
@@ -447,6 +448,26 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
integration={integrationInfo?.name}
/>
)}
+ {packageInfo && isRootPrivilegesRequired(packageInfo) ? (
+ <>
+
+ }
+ >
+
+
+
+ >
+ ) : null}
{numTransformAssets > 0 ? (
<>
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/overview.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/overview.tsx
index cd8fbebe7f2a3..517c0552f925b 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/overview.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/overview.tsx
@@ -23,6 +23,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
import {
isIntegrationPolicyTemplate,
isPackagePrerelease,
+ isRootPrivilegesRequired,
} from '../../../../../../../../common/services';
import {
@@ -37,6 +38,7 @@ import type { PackageInfo, RegistryPolicyTemplate } from '../../../../../types';
import { Screenshots } from './screenshots';
import { Readme } from './readme';
import { Details } from './details';
+import { Requirements } from './requirements';
interface Props {
packageInfo: PackageInfo;
@@ -277,6 +279,8 @@ export const OverviewPage: React.FC = memo(
];
}, [h1, navItems]);
+ const requireAgentRootPrivileges = isRootPrivilegesRequired(packageInfo);
+
return (
@@ -309,6 +313,11 @@ export const OverviewPage: React.FC = memo(
+ {requireAgentRootPrivileges ? (
+
+
+
+ ) : null}
{screenshots.length ? (
{
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ ),
+ },
+ ]}
+ />
+
+
+ );
+});