Skip to content

Commit db9d5b0

Browse files
[9.2] [UII] Use explicit fleet server & output IDs for agentless on ECH and Serverless (#225188) (#239212)
# Backport This will backport the following commits from `main` to `9.2`: - [[UII] Use explicit fleet server & output IDs for agentless on ECH and Serverless (#225188)](#225188) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Jen Huang","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-10-15T02:59:59Z","message":"[UII] Use explicit fleet server & output IDs for agentless on ECH and Serverless (#225188)","sha":"237a489648c48ab43701b77a0af380f5a7360cee","branchLabelMapping":{"^v9.3.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Fleet","v9.0.0","ci:cloud-deploy","ci:project-deploy-security","backport:version","v9.2.0","v9.3.0","v9.1.6","v8.19.6"],"title":"[UII] Use explicit fleet server & output IDs for agentless on ECH and Serverless","number":225188,"url":"https://github.com/elastic/kibana/pull/225188","mergeCommit":{"message":"[UII] Use explicit fleet server & output IDs for agentless on ECH and Serverless (#225188)","sha":"237a489648c48ab43701b77a0af380f5a7360cee"}},"sourceBranch":"main","suggestedTargetBranches":["9.0","9.2","9.1","8.19"],"targetPullRequestStates":[{"branch":"9.0","label":"v9.0.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"9.2","label":"v9.2.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.3.0","branchLabelMappingKey":"^v9.3.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/225188","number":225188,"mergeCommit":{"message":"[UII] Use explicit fleet server & output IDs for agentless on ECH and Serverless (#225188)","sha":"237a489648c48ab43701b77a0af380f5a7360cee"}},{"branch":"9.1","label":"v9.1.6","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.19","label":"v8.19.6","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Jen Huang <[email protected]>
1 parent 7919ed7 commit db9d5b0

File tree

18 files changed

+515
-41
lines changed

18 files changed

+515
-41
lines changed

x-pack/platform/plugins/shared/fleet/common/constants/fleet_server_policy_config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,12 @@ export const FLEET_PROXY_SAVED_OBJECT_TYPE = 'fleet-proxy';
1414
export const PROXY_URL_REGEX = /^(http[s]?|socks5):\/\/[^\s$.?#].[^\s]*$/gm;
1515

1616
export const SERVERLESS_DEFAULT_FLEET_SERVER_HOST_ID = 'default-fleet-server';
17+
18+
// Fleet Server IDs used for agentless policies:
19+
// - For ECH, this is created by Fleet, see `createCloudFleetServerHostsIfNeeded` in:
20+
// `x-pack/platform/plugins/shared/fleet/server/services/preconfiguration/fleet_server_host.ts`
21+
// - For Serverless, this is the `default-fleet-server` host that is created from
22+
// preconfiguration via project controller
23+
// - Both are uneditable by users due to having `is_preconfigured: true` set
24+
export const ECH_AGENTLESS_FLEET_SERVER_HOST_ID = 'internal-agentless-fleet-server';
25+
export const SERVERLESS_AGENTLESS_FLEET_SERVER_HOST_ID = SERVERLESS_DEFAULT_FLEET_SERVER_HOST_ID;

x-pack/platform/plugins/shared/fleet/common/constants/output.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@ export const DEFAULT_OUTPUT: NewOutput = {
2828

2929
export const SERVERLESS_DEFAULT_OUTPUT_ID = 'es-default-output';
3030

31+
// Output IDs used for agentless policies:
32+
// - For ECH, this is an output created by Fleet, see `ensureDefaultOutputs()` in
33+
// `x-pack/plugins/fleet/server/services/output.ts`
34+
// - For Serverless, this is the `es-default-output` output that is created from
35+
// preconfiguration via project controller
36+
// - Both are uneditable by users due to having `is_preconfigured: true` set
37+
export const ECH_AGENTLESS_OUTPUT_ID = 'es-agentless-output';
38+
export const SERVERLESS_AGENTLESS_OUTPUT_ID = SERVERLESS_DEFAULT_OUTPUT_ID;
39+
3140
export const LICENCE_FOR_PER_POLICY_OUTPUT = 'platinum';
3241
export const LICENCE_FOR_OUTPUT_PER_INTEGRATION = 'enterprise';
3342

x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ import { SelectedPolicyTab } from '../../components';
2121
import {
2222
AGENTLESS_AGENT_POLICY_INACTIVITY_TIMEOUT,
2323
AGENTLESS_AGENT_POLICY_MONITORING,
24-
SERVERLESS_DEFAULT_OUTPUT_ID,
25-
DEFAULT_OUTPUT_ID,
26-
SERVERLESS_DEFAULT_FLEET_SERVER_HOST_ID,
27-
DEFAULT_FLEET_SERVER_HOST_ID,
24+
ECH_AGENTLESS_OUTPUT_ID,
25+
SERVERLESS_AGENTLESS_OUTPUT_ID,
26+
ECH_AGENTLESS_FLEET_SERVER_HOST_ID,
27+
SERVERLESS_AGENTLESS_FLEET_SERVER_HOST_ID,
2828
} from '../../../../../../../../common/constants';
2929
import {
3030
isAgentlessIntegration as isAgentlessIntegrationFn,
@@ -153,9 +153,9 @@ export function useSetupTechnology({
153153
useEffect(() => {
154154
const fetchOutputId = async () => {
155155
const outputId = isServerless
156-
? SERVERLESS_DEFAULT_OUTPUT_ID
156+
? SERVERLESS_AGENTLESS_OUTPUT_ID
157157
: isCloud
158-
? DEFAULT_OUTPUT_ID
158+
? ECH_AGENTLESS_OUTPUT_ID
159159
: undefined;
160160
if (outputId) {
161161
const outputData = await sendGetOneOutput(outputId);
@@ -166,9 +166,9 @@ export function useSetupTechnology({
166166
};
167167
const fetchFleetServerHostId = async () => {
168168
const hostId = isServerless
169-
? SERVERLESS_DEFAULT_FLEET_SERVER_HOST_ID
169+
? SERVERLESS_AGENTLESS_FLEET_SERVER_HOST_ID
170170
: isCloud
171-
? DEFAULT_FLEET_SERVER_HOST_ID
171+
? ECH_AGENTLESS_FLEET_SERVER_HOST_ID
172172
: undefined;
173173

174174
if (hostId) {
@@ -214,7 +214,12 @@ export function useSetupTechnology({
214214
inactivity_timeout: AGENTLESS_AGENT_POLICY_INACTIVITY_TIMEOUT,
215215
supports_agentless: true,
216216
monitoring_enabled: AGENTLESS_AGENT_POLICY_MONITORING,
217-
...(agentlessPolicyOutputId ? { data_output_id: agentlessPolicyOutputId } : {}),
217+
...(agentlessPolicyOutputId
218+
? {
219+
data_output_id: agentlessPolicyOutputId,
220+
monitoring_output_id: agentlessPolicyOutputId,
221+
}
222+
: {}),
218223
...(agentlessPolicyFleetServerHostId
219224
? { fleet_server_host_id: agentlessPolicyFleetServerHostId }
220225
: {}),

x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/index.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,20 @@ import { OutputFormLogstashSection } from './output_form_logstash';
6363
import { OutputFormElasticsearchSection } from './output_form_elasticsearch';
6464

6565
export interface EditOutputFlyoutProps {
66-
defaultOuput?: Output;
66+
defaultOutput?: Output;
6767
output?: Output;
6868
onClose: () => void;
6969
proxies: FleetProxy[];
7070
}
7171

7272
export const EditOutputFlyout: React.FunctionComponent<EditOutputFlyoutProps> = ({
73-
defaultOuput,
73+
defaultOutput,
7474
onClose,
7575
output,
7676
proxies,
7777
}) => {
7878
useBreadcrumbs('settings');
79-
const form = useOutputForm(onClose, output, defaultOuput);
79+
const form = useOutputForm(onClose, output, defaultOutput);
8080
const inputs = form.inputs;
8181
const { docLinks, cloud } = useStartServices();
8282
const fleetStatus = useFleetStatus();

x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/use_output_form.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ export function extractDefaultDynamicKafkaTopics(
194194
];
195195
}
196196

197-
export function useOutputForm(onSucess: () => void, output?: Output, defaultOuput?: Output) {
197+
export function useOutputForm(onSucess: () => void, output?: Output, defaultOutput?: Output) {
198198
const fleetStatus = useFleetStatus();
199199
const authz = useAuthz();
200200

@@ -255,7 +255,7 @@ export function useOutputForm(onSucess: () => void, output?: Output, defaultOupu
255255
const isServerless = cloud?.isServerlessEnabled;
256256
// Set the hosts to default for new ES output in serverless.
257257
const elasticsearchUrlDefaultValue =
258-
isServerless && !output?.hosts ? defaultOuput?.hosts || [] : output?.hosts || [];
258+
isServerless && !output?.hosts ? defaultOutput?.hosts || [] : output?.hosts || [];
259259
const elasticsearchUrlDisabled = isServerless || isDisabled('hosts');
260260
const elasticsearchUrlInput = useComboInput(
261261
'esHostsComboxBox',

x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/settings/index.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export const SettingsApp = withConfirmModalProvider(() => {
8484
]);
8585

8686
const { cloud } = useStartServices();
87+
const isServerlessEnabled = cloud?.isServerlessEnabled;
8788

8889
if (
8990
(outputs.isLoading && outputs.isInitialRequest) ||
@@ -127,7 +128,7 @@ export const SettingsApp = withConfirmModalProvider(() => {
127128
</Route>
128129
<Route path={FLEET_ROUTING_PATHS.settings_create_fleet_server_hosts}>
129130
<EuiPortal>
130-
{cloud?.isServerlessEnabled ? (
131+
{isServerlessEnabled ? (
131132
<FleetServerHostsFlyout
132133
proxies={proxies.data?.items ?? []}
133134
onClose={onCloseCallback}
@@ -145,7 +146,11 @@ export const SettingsApp = withConfirmModalProvider(() => {
145146
<EditOutputFlyout
146147
proxies={proxies.data.items}
147148
onClose={onCloseCallback}
148-
defaultOuput={outputs.data?.items.find((o) => o.id === SERVERLESS_DEFAULT_OUTPUT_ID)}
149+
defaultOutput={
150+
isServerlessEnabled
151+
? outputs.data?.items.find((o) => o.id === SERVERLESS_DEFAULT_OUTPUT_ID)
152+
: undefined
153+
}
149154
/>
150155
</EuiPortal>
151156
</Route>
@@ -182,9 +187,11 @@ export const SettingsApp = withConfirmModalProvider(() => {
182187
proxies={proxies.data?.items ?? []}
183188
onClose={onCloseCallback}
184189
output={output}
185-
defaultOuput={outputs.data?.items.find(
186-
(o) => o.id === SERVERLESS_DEFAULT_OUTPUT_ID
187-
)}
190+
defaultOutput={
191+
isServerlessEnabled
192+
? outputs.data?.items.find((o) => o.id === SERVERLESS_DEFAULT_OUTPUT_ID)
193+
: undefined
194+
}
188195
/>
189196
</EuiPortal>
190197
);

x-pack/platform/plugins/shared/fleet/server/constants/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ export {
6363
DEFAULT_OUTPUT,
6464
DEFAULT_OUTPUT_ID,
6565
SERVERLESS_DEFAULT_OUTPUT_ID,
66+
ECH_AGENTLESS_OUTPUT_ID,
67+
SERVERLESS_AGENTLESS_OUTPUT_ID,
6668
PACKAGE_POLICY_DEFAULT_INDEX_PRIVILEGES,
6769
AGENT_POLICY_DEFAULT_MONITORING_DATASETS,
6870
// Fleet Server index
@@ -84,6 +86,8 @@ export {
8486
DEFAULT_FLEET_SERVER_HOST_ID,
8587
FLEET_SERVER_HOST_SAVED_OBJECT_TYPE,
8688
SERVERLESS_DEFAULT_FLEET_SERVER_HOST_ID,
89+
ECH_AGENTLESS_FLEET_SERVER_HOST_ID,
90+
SERVERLESS_AGENTLESS_FLEET_SERVER_HOST_ID,
8791
FLEET_SERVER_PACKAGE,
8892
// Proxy
8993
FLEET_PROXY_SAVED_OBJECT_TYPE,

x-pack/platform/plugins/shared/fleet/server/services/agent_policy.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ describe('Agent policy', () => {
447447
updated_by: 'system',
448448
schema_version: '1.1.1',
449449
is_protected: false,
450-
fleet_server_host_id: 'fleet-default-fleet-server-host',
450+
fleet_server_host_id: 'internal-agentless-fleet-server',
451451
});
452452
});
453453

x-pack/platform/plugins/shared/fleet/server/services/agentless_settings_ids.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ describe('correct agentless policy settings', () => {
7070
'agent_policy_1',
7171
{
7272
data_output_id: 'es-default-output',
73+
monitoring_output_id: 'es-default-output',
7374
fleet_server_host_id: 'default-fleet-server',
7475
},
7576
{
@@ -82,6 +83,7 @@ describe('correct agentless policy settings', () => {
8283
'agent_policy_2',
8384
{
8485
data_output_id: 'es-default-output',
86+
monitoring_output_id: 'es-default-output',
8587
fleet_server_host_id: 'default-fleet-server',
8688
},
8789
{

x-pack/platform/plugins/shared/fleet/server/services/agentless_settings_ids.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export async function ensureCorrectAgentlessSettingsIds(esClient: ElasticsearchC
3535
const internalSoClientWithoutSpaceExtension =
3636
appContextService.getInternalUserSOClientWithoutSpaceExtension();
3737

38-
const agentlessOutputIdsToFix = correctOutputId
38+
const agentlessDataOutputIdsToFix = correctOutputId
3939
? (
4040
await internalSoClientWithoutSpaceExtension.find<AgentPolicySOAttributes>({
4141
type: agentPolicySavedObjectType,
@@ -48,6 +48,19 @@ export async function ensureCorrectAgentlessSettingsIds(esClient: ElasticsearchC
4848
)?.saved_objects.map((so) => so.id)
4949
: [];
5050

51+
const agentlessMonitoringOutputIdsToFix = correctOutputId
52+
? (
53+
await internalSoClientWithoutSpaceExtension.find<AgentPolicySOAttributes>({
54+
type: agentPolicySavedObjectType,
55+
page: 1,
56+
perPage: SO_SEARCH_LIMIT,
57+
filter: `${agentPolicySavedObjectType}.attributes.supports_agentless:true AND NOT ${agentPolicySavedObjectType}.attributes.monitoring_output_id:${correctOutputId}`,
58+
fields: [`id`],
59+
namespaces: ['*'],
60+
})
61+
)?.saved_objects.map((so) => so.id)
62+
: [];
63+
5164
const agentlessFleetServerIdsToFix = correctFleetServerId
5265
? (
5366
await internalSoClientWithoutSpaceExtension.find<AgentPolicySOAttributes>({
@@ -63,15 +76,18 @@ export async function ensureCorrectAgentlessSettingsIds(esClient: ElasticsearchC
6376

6477
try {
6578
// Check that the output ID exists
66-
if (correctOutputId && agentlessOutputIdsToFix?.length > 0) {
79+
if (
80+
correctOutputId &&
81+
(agentlessDataOutputIdsToFix?.length > 0 || agentlessMonitoringOutputIdsToFix?.length > 0)
82+
) {
6783
const output = await outputService.get(
6884
internalSoClientWithoutSpaceExtension,
6985
correctOutputId
7086
);
7187
fixOutput = output != null;
7288
}
7389
} catch (e) {
74-
// Silently swallow
90+
// Silently swallow so that output will not be fixed if the correct output ID does not exist
7591
}
7692

7793
try {
@@ -84,12 +100,13 @@ export async function ensureCorrectAgentlessSettingsIds(esClient: ElasticsearchC
84100
fixFleetServer = fleetServerHost != null;
85101
}
86102
} catch (e) {
87-
// Silently swallow
103+
// Silently swallow so that fleet server host will not be fixed if the correct fleet server host ID does not exist
88104
}
89105

90106
const allIdsToFix = Array.from(
91107
new Set([
92-
...(fixOutput ? agentlessOutputIdsToFix : []),
108+
...(fixOutput ? agentlessDataOutputIdsToFix : []),
109+
...(fixOutput ? agentlessMonitoringOutputIdsToFix : []),
93110
...(fixFleetServer ? agentlessFleetServerIdsToFix : []),
94111
])
95112
);
@@ -100,9 +117,7 @@ export async function ensureCorrectAgentlessSettingsIds(esClient: ElasticsearchC
100117

101118
appContextService
102119
.getLogger()
103-
.debug(
104-
`Fixing output and/or fleet server host IDs on agent policies: ${agentlessOutputIdsToFix}`
105-
);
120+
.debug(`Fixing output and/or fleet server host IDs on agent policies: ${allIdsToFix}`);
106121

107122
await pMap(
108123
allIdsToFix,
@@ -113,6 +128,7 @@ export async function ensureCorrectAgentlessSettingsIds(esClient: ElasticsearchC
113128
agentPolicyId,
114129
{
115130
data_output_id: correctOutputId,
131+
monitoring_output_id: correctOutputId,
116132
fleet_server_host_id: correctFleetServerId,
117133
},
118134
{

0 commit comments

Comments
 (0)