kibana/x-pack/test/fleet_api_integration/apis/agents/migrate.ts
Mason Herron d3f6fb9870
[Fleet] Add feature-flag gate for single agent migrations UI/API & bulk migration API (#224143)
## Summary

Closes https://github.com/elastic/ingest-dev/issues/5694

- Adds a feature flag gate for the `single` agent migration UI and API
- Also gates the bulk migrate `endpoint`, UI will be gated separately as
part of
https://github.com/elastic/kibana/pull/224334

### Checklist

Check the PR satisfies following conditions. 

Reviewers should verify this PR satisfies this list as well.

- [ ] 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/src/platform/packages/shared/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [ ] [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
- [ ] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [ ] This was checked for breaking HTTP API changes, and any breaking
changes have been approved by the breaking-change committee. The
`release_note:breaking` label should be applied in these situations.
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [ ] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

### Identify risks

N/A

---------

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
2025-06-18 18:11:45 +02:00

276 lines
8.7 KiB
TypeScript

/*
* 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 { AGENTS_INDEX } from '@kbn/fleet-plugin/common';
import { FtrProviderContext } from '../../../api_integration/ftr_provider_context';
export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
const esArchiver = getService('esArchiver');
const supertest = getService('supertest');
const es = getService('es');
describe('fleet_agents_migrate', () => {
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/fleet/agents');
// Create agent policies using the Fleet API
// Policy 1 - regular policy without tamper protection
const policy1Response = await supertest
.post(`/api/fleet/agent_policies`)
.set('kbn-xsrf', 'xx')
.send({
name: 'Policy 1',
namespace: 'default',
description: 'Test policy 1',
monitoring_enabled: ['logs', 'metrics'],
})
.expect(200);
const policy1 = policy1Response.body.item;
// Policy 2 - with tamper protection
const policy2Response = await supertest
.post(`/api/fleet/agent_policies`)
.set('kbn-xsrf', 'xx')
.send({
name: 'Policy 2',
namespace: 'default',
description: 'Test policy 2 with tamper protection',
monitoring_enabled: ['logs', 'metrics'],
})
.expect(200);
const policy2 = policy2Response.body.item;
// First, install the endpoint package which is required for the endpoint package policy
await supertest
.post('/api/fleet/epm/packages/endpoint')
.set('kbn-xsrf', 'xx')
.send({ force: true })
.expect(200);
// Fetch the installed package to get its current version
const packageInfoResponse = await supertest
.get('/api/fleet/epm/packages/endpoint')
.set('kbn-xsrf', 'xx')
.expect(200);
const endpointPackageVersion = packageInfoResponse.body.item.version;
// Create Elastic Defend package policy for policy2 with proper configuration
await supertest
.post(`/api/fleet/package_policies`)
.set('kbn-xsrf', 'xx')
.send({
name: 'endpoint-1',
description: 'Endpoint Security Integration',
namespace: 'default',
policy_id: policy2.id,
enabled: true,
inputs: [
{
type: 'endpoint',
enabled: true,
streams: [],
config: {
policy: {
value: {
windows: {
events: {
dll_and_driver_load: true,
dns: true,
file: true,
network: true,
process: true,
registry: true,
security: true,
},
malware: { mode: 'prevent' },
ransomware: { mode: 'prevent' },
memory_protection: { mode: 'prevent' },
behavior_protection: { mode: 'prevent' },
popup: {
malware: { enabled: true, message: '' },
ransomware: { enabled: true, message: '' },
},
},
mac: {
events: { file: true, network: true, process: true },
malware: { mode: 'prevent' },
behavior_protection: { mode: 'prevent' },
popup: { malware: { enabled: true, message: '' } },
},
linux: {
events: { file: true, network: true, process: true },
malware: { mode: 'prevent' },
behavior_protection: { mode: 'prevent' },
popup: { malware: { enabled: true, message: '' } },
},
},
},
},
},
],
package: {
name: 'endpoint',
title: 'Elastic Defend',
version: endpointPackageVersion, // Use the actual installed version
},
})
.expect(200);
// Now enable tamper protection on policy2
await supertest
.put(`/api/fleet/agent_policies/${policy2.id}`)
.set('kbn-xsrf', 'xx')
.send({
name: policy2.name,
namespace: 'default',
description: policy2.description,
is_protected: true, // Enable tamper protection
})
.expect(200);
// Create agents in Elasticsearch
await es.index({
refresh: 'wait_for',
index: AGENTS_INDEX,
id: 'agent1',
document: {
policy_id: policy1.id,
},
});
await es.index({
refresh: 'wait_for',
index: AGENTS_INDEX,
id: 'agent2',
document: {
policy_id: policy2.id, // Policy 2 is tamper protected
},
});
await es.index({
refresh: 'wait_for',
index: AGENTS_INDEX,
id: 'agent3',
document: {
policy_id: policy1.id,
components: [
{
type: 'fleet-server',
id: 'fleet-server',
revision: 1,
},
],
},
});
});
after(async () => {
await esArchiver.unload('x-pack/test/functional/es_archives/fleet/agents');
// Cleanup will be handled automatically by Fleet API
});
describe('POST /agents/{agentId}/migrate', () => {
it('should return a 200 if the migration action is successful', async () => {
const {} = await supertest
.post(`/api/fleet/agents/agent1/migrate`)
.set('kbn-xsrf', 'xx')
.send({
enrollment_token: '1234',
uri: 'https://example.com',
})
.expect(200);
});
it('should return a 403 if the agent is tamper protected', async () => {
const {} = await supertest
.post(`/api/fleet/agents/agent2/migrate`)
.set('kbn-xsrf', 'xx')
.send({
enrollment_token: '1234',
uri: 'https://example.com',
})
.expect(403);
});
it('should return a 403 if the agent is a fleet-agent', async () => {
const {} = await supertest
.post(`/api/fleet/agents/agent3/migrate`)
.set('kbn-xsrf', 'xx')
.send({
enrollment_token: '1234',
uri: 'https://example.com',
})
.expect(403);
});
it('should return a 404 when agent does not exist', async () => {
await supertest
.post(`/api/fleet/agents/agent100/migrate`)
.set('kbn-xsrf', 'xx')
.send({
enrollment_token: '1234',
uri: 'https://example.com',
})
.expect(404);
});
});
// Bulk migrate agents
describe('POST /agents/bulk_migrate', () => {
it('should return a 200 if the migration action is successful', async () => {
const {} = await supertest
.post(`/api/fleet/agents/bulk_migrate`)
.set('kbn-xsrf', 'xx')
.send({
agents: ['agent1'],
uri: 'https://example.com',
enrollment_token: '1234',
})
.expect(200);
});
it('should return a 403 if any agent is tamper protected', async () => {
const {} = await supertest
.post(`/api/fleet/agents/bulk_migrate`)
.set('kbn-xsrf', 'xx')
.send({
agents: ['agent1', 'agent2'],
uri: 'https://example.com',
enrollment_token: '1234',
})
.expect(403);
});
it('should return a 403 if any agent is a fleet-agent', async () => {
const {} = await supertest
.post(`/api/fleet/agents/bulk_migrate`)
.set('kbn-xsrf', 'xx')
.send({
agents: ['agent1', 'agent3'],
uri: 'https://example.com',
enrollment_token: '1234',
})
.expect(403);
});
it('should return a 404 when any agent does not exist', async () => {
await supertest
.post(`/api/fleet/agents/bulk_migrate`)
.set('kbn-xsrf', 'xx')
.send({
agents: ['agent100', 'agent400', 'agent1'],
uri: 'https://example.com',
enrollment_token: '1234',
})
.expect(404);
});
});
});
}