diff --git a/x-pack/platform/plugins/shared/content_connectors/server/services/index.test.ts b/x-pack/platform/plugins/shared/content_connectors/server/services/index.test.ts index 4b8c2b1d2bc68..428886c7e59a7 100644 --- a/x-pack/platform/plugins/shared/content_connectors/server/services/index.test.ts +++ b/x-pack/platform/plugins/shared/content_connectors/server/services/index.test.ts @@ -31,13 +31,6 @@ import { } from '@kbn/fleet-plugin/server'; import { AgentPolicy, PackagePolicy, PackagePolicyInput } from '@kbn/fleet-plugin/common'; import { createAgentPolicyMock, createPackagePolicyMock } from '@kbn/fleet-plugin/common/mocks'; -import { createAgentPolicyWithPackages } from '@kbn/fleet-plugin/server/services/agent_policy_create'; - -jest.mock('@kbn/fleet-plugin/server/services/agent_policy_create', () => { - return { - createAgentPolicyWithPackages: jest.fn().mockReturnValue({ id: 'test-policy' }), - }; -}); jest.mock('@kbn/fleet-plugin/server/services/epm/packages', () => { const mockedGetPackageInfo = ({ pkgName }: { pkgName: string }) => { @@ -451,7 +444,7 @@ describe('AgentlessConnectorsInfraService', () => { } }); - test('Does not swallow an error if agent policy creation failed', async () => { + test('Does not swallow an error if agent with package policies creation failed', async () => { const connector = { id: '000000001', name: 'something', @@ -460,29 +453,7 @@ describe('AgentlessConnectorsInfraService', () => { }; const errorMessage = 'Failed to create an agent policy hehe'; - (createAgentPolicyWithPackages as jest.Mock).mockImplementationOnce(() => { - throw new Error(errorMessage); - }); - - try { - await service.deployConnector(connector); - expect(true).toBe(false); - } catch (e) { - expect(e.message).toEqual(errorMessage); - } - }); - - test('Does not swallow an error if package policy creation failed', async () => { - const connector = { - id: '000000001', - name: 'something', - service_type: 'github', - is_deleted: false, - }; - const errorMessage = 'Failed to create a package policy hehe'; - - agentPolicyInterface.create.mockResolvedValue(agentPolicy); - packagePolicyService.create.mockImplementation(() => { + agentPolicyInterface.createWithPackagePolicies.mockImplementationOnce(() => { throw new Error(errorMessage); }); @@ -494,7 +465,7 @@ describe('AgentlessConnectorsInfraService', () => { } }); - test('Returns a created package policy when all goes well', async () => { + test('Returns a created agent policy when all goes well', async () => { const connector = { id: '000000001', name: 'something', @@ -502,11 +473,10 @@ describe('AgentlessConnectorsInfraService', () => { is_deleted: false, }; - agentPolicyInterface.create.mockResolvedValue(agentPolicy); - packagePolicyService.create.mockResolvedValue(sharepointOnlinePackagePolicy); + agentPolicyInterface.createWithPackagePolicies.mockResolvedValue(agentPolicy); const result = await service.deployConnector(connector); - expect(result).toBe(sharepointOnlinePackagePolicy); + expect(result).toBe(agentPolicy); }); test('passes supports_agentless flag and global tags correctly to agent policy creation and package policy creation', async () => { @@ -518,27 +488,27 @@ describe('AgentlessConnectorsInfraService', () => { }; const fakeAgentPolicy = { id: 'agent-policy-005' } as AgentPolicy; - const fakePackagePolicy = { - id: 'package-policy-005', - policy_ids: ['agent-policy-005'], - } as PackagePolicy; - - agentPolicyInterface.create.mockResolvedValue(fakeAgentPolicy); - packagePolicyService.create.mockResolvedValue(fakePackagePolicy); + agentPolicyInterface.createWithPackagePolicies.mockResolvedValue(fakeAgentPolicy); const result = await service.deployConnector(testConnector); - expect(createAgentPolicyWithPackages).toHaveBeenCalled(); - - expect(packagePolicyService.create).toHaveBeenCalledWith( - soClient, - esClient, + expect(agentPolicyInterface.createWithPackagePolicies).toHaveBeenCalledWith( expect.objectContaining({ - supports_agentless: true, - }), - { force: true } + soClient, + esClient, + agentPolicy: expect.objectContaining({ + supports_agentless: true, + }), + packagePolicies: expect.arrayContaining([ + expect.objectContaining({ + supports_agentless: true, + }), + ]), + options: expect.objectContaining({ force: true }), + }) ); - expect(result).toBe(fakePackagePolicy); + + expect(result).toBe(fakeAgentPolicy); }); }); describe('removeDeployment', () => { diff --git a/x-pack/platform/plugins/shared/content_connectors/server/services/index.ts b/x-pack/platform/plugins/shared/content_connectors/server/services/index.ts index fe20cb1435190..726001d1f1dfa 100644 --- a/x-pack/platform/plugins/shared/content_connectors/server/services/index.ts +++ b/x-pack/platform/plugins/shared/content_connectors/server/services/index.ts @@ -6,7 +6,12 @@ */ import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import { Agent, PACKAGE_POLICY_SAVED_OBJECT_TYPE, PackagePolicy } from '@kbn/fleet-plugin/common'; +import { + Agent, + AgentPolicy, + NewAgentPolicy, + PACKAGE_POLICY_SAVED_OBJECT_TYPE, +} from '@kbn/fleet-plugin/common'; import { AgentPolicyServiceInterface, AgentService, @@ -15,7 +20,6 @@ import { import type { Logger, SavedObjectsClientContract } from '@kbn/core/server'; import { NATIVE_CONNECTOR_DEFINITIONS, fetchConnectors } from '@kbn/search-connectors'; import { getPackageInfo } from '@kbn/fleet-plugin/server/services/epm/packages'; -import { createAgentPolicyWithPackages } from '@kbn/fleet-plugin/server/services/agent_policy_create'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; export interface ConnectorMetadata { @@ -160,7 +164,7 @@ export class AgentlessConnectorsInfraService { return policiesMetadata; }; - public deployConnector = async (connector: ConnectorMetadata): Promise => { + public deployConnector = async (connector: ConnectorMetadata): Promise => { this.logger.info( `Connector ${connector.id} has no integration policy associated with it, creating` ); @@ -186,77 +190,73 @@ export class AgentlessConnectorsInfraService { const pkgVersion = await this.getPackageVersion(); this.logger.debug(`Latest package version for ${pkgName} is ${pkgVersion}`); - const createdPolicy = await createAgentPolicyWithPackages({ + const agentPolicyToCreate: NewAgentPolicy = { + name: `Agentless policy for ${connector.service_type} connector: ${connector.id}`, + description: `Automatically generated on ${new Date(Date.now()).toISOString()}`, + global_data_tags: [ + { + name: 'organization', + value: 'elastic', + }, + { + name: 'division', + value: 'engineering', + }, + { + name: 'team', + value: 'search-extract-and-transform', + }, + ], + namespace: 'default', + monitoring_enabled: ['logs', 'metrics'], + inactivity_timeout: 3600, + is_protected: false, + supports_agentless: true, + }; + + const packagePolicyToCreate = { + package: { + title: pkgTitle, + name: pkgName, + version: pkgVersion, + }, + name: `${connector.service_type} connector ${connector.id}`, + description: '', + namespace: '', + enabled: true, + inputs: [ + { + type: connectorsInputName, + policy_template: connector.service_type, + enabled: true, + vars: { + connector_id: { type: 'string', value: connector.id }, + connector_name: { type: 'string', value: connector.name }, + service_type: { type: 'string', value: connector.service_type }, + }, + streams: [], + }, + ], + supports_agentless: true, + }; + + const agentPolicy = await this.agentPolicyService.createWithPackagePolicies({ soClient: this.soClient, esClient: this.esClient, - newPolicy: { - name: `Agentless policy for ${connector.service_type} connector: ${connector.id}`, - description: `Automatically generated on ${new Date(Date.now()).toISOString()}`, - global_data_tags: [ - { - name: 'organization', - value: 'elastic', - }, - { - name: 'division', - value: 'engineering', - }, - { - name: 'team', - value: 'search-extract-and-transform', - }, - ], - namespace: 'default', - monitoring_enabled: ['logs', 'metrics'], - inactivity_timeout: 3600, - is_protected: false, - supports_agentless: true, + agentPolicy: agentPolicyToCreate, + packagePolicies: [packagePolicyToCreate], + options: { + withSysMonitoring: true, + spaceId: this.soClient.getCurrentNamespace() ?? DEFAULT_SPACE_ID, + force: true, }, - withSysMonitoring: true, - spaceId: this.soClient.getCurrentNamespace() ?? DEFAULT_SPACE_ID, }); this.logger.info( - `Successfully created agent policy ${createdPolicy.id} for agentless connector ${connector.id}` - ); - this.logger.debug(`Creating a package policy for agentless connector ${connector.id}`); - const packagePolicy = await this.packagePolicyService.create( - this.soClient, - this.esClient, - { - policy_ids: [createdPolicy.id], - package: { - title: pkgTitle, - name: pkgName, - version: pkgVersion, - }, - name: `${connector.service_type} connector ${connector.id}`, - description: '', - namespace: '', - enabled: true, - inputs: [ - { - type: connectorsInputName, - policy_template: connector.service_type, - enabled: true, - vars: { - connector_id: { type: 'string', value: connector.id }, - connector_name: { type: 'string', value: connector.name }, - service_type: { type: 'string', value: connector.service_type }, - }, - streams: [], - }, - ], - supports_agentless: true, - }, - { force: true } - ); - - this.logger.info( - `Successfully created package policy ${packagePolicy.id} for agentless connector ${connector.id}` + `Successfully created agent policy ${agentPolicy.id} for agentless connector ${connector.id}` ); - return packagePolicy; + return agentPolicy; }; public removeDeployment = async (packagePolicyId: string): Promise => { diff --git a/x-pack/platform/plugins/shared/content_connectors/server/task.test.ts b/x-pack/platform/plugins/shared/content_connectors/server/task.test.ts index e1ad9fedd4384..c1c8b26f5cbc1 100644 --- a/x-pack/platform/plugins/shared/content_connectors/server/task.test.ts +++ b/x-pack/platform/plugins/shared/content_connectors/server/task.test.ts @@ -14,7 +14,7 @@ import { PackagePolicyMetadata, } from './services'; import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; -import { createPackagePolicyMock } from '@kbn/fleet-plugin/common/mocks'; +import { createAgentPolicyMock } from '@kbn/fleet-plugin/common/mocks'; import { coreMock } from '@kbn/core/server/mocks'; import { AgentlessConnectorsInfraServiceFactory } from './services/infra_service_factory'; @@ -218,7 +218,7 @@ describe('infraSyncTaskRunner', () => { throw new Error('Cannot deploy these connectors'); } - return createPackagePolicyMock(); + return createAgentPolicyMock(); }); await infraSyncTaskRunner( diff --git a/x-pack/platform/plugins/shared/fleet/server/mocks/index.ts b/x-pack/platform/plugins/shared/fleet/server/mocks/index.ts index b6feab804c115..8765baef3b3f4 100644 --- a/x-pack/platform/plugins/shared/fleet/server/mocks/index.ts +++ b/x-pack/platform/plugins/shared/fleet/server/mocks/index.ts @@ -274,6 +274,7 @@ export const createPackagePolicyServiceMock = (): jest.Mocked => { return { create: jest.fn().mockReturnValue(Promise.resolve()), + createWithPackagePolicies: jest.fn().mockReturnValue(Promise.resolve()), get: jest.fn().mockReturnValue(Promise.resolve()), list: jest.fn().mockReturnValue(Promise.resolve()), delete: jest.fn().mockReturnValue(Promise.resolve()), @@ -282,6 +283,7 @@ export const createMockAgentPolicyService = (): jest.Mocked; mockedAppContextService.getSecuritySetup.mockImplementation(() => ({ @@ -147,6 +149,9 @@ const mockedPackagePolicyService = packagePolicyService as jest.Mocked >; +const mockedCreateAgentPolicyWithPackages = createAgentPolicyWithPackages as jest.MockedFunction< + typeof createAgentPolicyWithPackages +>; function getAgentPolicyCreateMock() { const soClient = createSavedObjectClientMock(); @@ -536,6 +541,135 @@ describe('Agent policy', () => { }); }); + describe('createWithPackagePolicies', () => { + let deleteSpy: any; + beforeEach(() => { + deleteSpy = jest.spyOn(agentPolicyService, 'delete'); + }); + + afterEach(() => { + deleteSpy.mockRestore(); + }); + it('should create an agent policy with package policies', async () => { + const soClient = createSavedObjectClientMock(); + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + const mockAgentPolicy = { + name: 'Test Agent Policy', + namespace: 'default', + description: 'A test agent policy with package policies', + is_managed: false, + supports_agentless: true, + }; + const mockPackagePolicy = { + name: 'Test Package Policy', + policy_ids: [], + package: { name: 'test-package', title: 'Test Package', version: '1.0.0' }, + inputs: [], + enabled: true, + }; + + mockedCreateAgentPolicyWithPackages.mockResolvedValue(mockAgentPolicy as any); + mockedPackagePolicyService.create.mockResolvedValue(mockPackagePolicy as any); + soClient.bulkGet.mockResolvedValueOnce({ + saved_objects: [ + { + id: 'test-agent-policy', + attributes: { + name: mockAgentPolicy.name, + }, + }, + ], + } as any); + const agentPolicy = await agentPolicyService.createWithPackagePolicies({ + soClient, + esClient, + agentPolicy: mockAgentPolicy, + packagePolicies: [mockPackagePolicy], + options: { withSysMonitoring: true, spaceId: 'default' }, + }); + + expect(agentPolicy.name).toEqual(mockAgentPolicy.name); + }); + + it('should throw error if a package policy creation fails and delete all policies', async () => { + const soClient = createSavedObjectClientMock(); + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + mockedAppContextService.getInternalUserSOClient.mockReturnValue(soClient); + mockedAppContextService.getInternalUserESClient.mockReturnValue(esClient); + + const mockAgentPolicy = { + name: 'Test Agent Policy', + namespace: 'default', + description: 'A test agent policy with package policies', + is_managed: false, + supports_agentless: true, + }; + const mockAgentPolicyId = 'test-agent-policy-id'; + const mockPackagePolicy1 = { + name: 'Test Package Policy 1', + policy_ids: [], + package: { name: 'test-package1', title: 'Test Package1', version: '1.0.0' }, + inputs: [], + enabled: true, + }; + const packagePolicy1Id = 'package-policy-1-id'; + + const mockPackagePolicy2 = { + name: 'Test Package Policy 2', + policy_ids: [], + package: { name: 'test-package2', title: 'Test Package2', version: '1.0.0' }, + inputs: [], + enabled: true, + }; + + const mockError = new Error('Package policy creation failed'); + + mockedCreateAgentPolicyWithPackages.mockResolvedValue({ + id: mockAgentPolicyId, + ...mockAgentPolicy, + } as any); + mockedPackagePolicyService.create.mockImplementation( + (_soClient, _esClient, packagePolicy) => { + if (packagePolicy.name === 'Test Package Policy 2') { + throw mockError; + } else { + return Promise.resolve({ id: packagePolicy1Id, ...packagePolicy } as any); + } + } + ); + + deleteSpy.mockResolvedValueOnce({ id: mockAgentPolicyId, name: mockAgentPolicy.name }); + + let error; + + try { + await agentPolicyService.createWithPackagePolicies({ + soClient, + esClient, + agentPolicy: mockAgentPolicy, + packagePolicies: [mockPackagePolicy1, mockPackagePolicy2], + options: { withSysMonitoring: true, spaceId: 'default' }, + }); + } catch (e) { + error = e; + } + + expect(error).toEqual(mockError); + expect(deleteSpy).toHaveBeenCalledWith( + expect.anything(), + expect.anything(), + mockAgentPolicyId, + expect.anything() + ); + expect(mockedPackagePolicyService.delete).toHaveBeenCalledWith( + expect.anything(), + expect.anything(), + [packagePolicy1Id], + expect.anything() + ); + }); + }); + // TODO: Add more test coverage to `get` service method describe('get', () => { it('should call audit logger', async () => { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts index b9a841b73a449..841815e15b20e 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts @@ -120,6 +120,7 @@ import { getPackagePolicySavedObjectType, packagePolicyService } from './package import { incrementPackagePolicyCopyName } from './package_policies'; import { outputService } from './output'; import { agentPolicyUpdateEventHandler } from './agent_policy_update'; +import { createAgentPolicyWithPackages } from './agent_policy_create'; import { escapeSearchQueryPhrase, normalizeKuery as _normalizeKuery } from './saved_object'; import { getFullAgentPolicy, @@ -504,6 +505,125 @@ class AgentPolicyService { return { id: newSo.id, ...newSo.attributes }; } + public async createWithPackagePolicies({ + soClient, + esClient, + agentPolicy, + packagePolicies, + options: { + hasFleetServer, + withSysMonitoring, + monitoringEnabled, + spaceId, + user, + authorizationHeader, + force, + }, + }: { + soClient: SavedObjectsClientContract; + esClient: ElasticsearchClient; + agentPolicy: NewAgentPolicy; + packagePolicies: Array>; + options: { + hasFleetServer?: boolean; + withSysMonitoring: boolean; + monitoringEnabled?: string[]; + spaceId: string; + user?: AuthenticatedUser; + authorizationHeader?: HTTPAuthorizationHeader | null; + force?: boolean; + }; + }) { + const logger = appContextService.getLogger().get('createWithPackagePolicies'); + + logger.debug(`Creating agent policy ${agentPolicy.name} with package policies`); + + const newAgentPolicy = await createAgentPolicyWithPackages({ + soClient, + esClient, + agentPolicyService: this, + newPolicy: agentPolicy, + hasFleetServer, + withSysMonitoring, + monitoringEnabled, + spaceId, + user, + authorizationHeader, + force, + }); + + const createdPackagePolicyIds = []; + + try { + for (const packagePolicy of packagePolicies) { + const newPackagePolicy: NewPackagePolicy = { + ...packagePolicy, + policy_ids: [newAgentPolicy.id], + }; + + logger.debug( + `Creating package policy ${packagePolicy.name} for agent policy ${newAgentPolicy.name}` + ); + + const createdPackagePolicy = await packagePolicyService.create( + soClient, + esClient, + newPackagePolicy, + { + spaceId, + user, + bumpRevision: false, + authorizationHeader, + force, + } + ); + + createdPackagePolicyIds.push(createdPackagePolicy.id); + } + + const agentPolicyWithPackagePolicies = await this.get(soClient, newAgentPolicy.id); + + if (!agentPolicyWithPackagePolicies) { + throw new AgentPolicyNotFoundError( + `Could not retrieve created agent policy ${newAgentPolicy.id} after creating its package policies` + ); + } + + return agentPolicyWithPackagePolicies; + } catch (e) { + logger.error( + `Error creating package policies for agent policy ${newAgentPolicy.id}: ${e.message}` + ); + logger.debug( + `Rolling back policy creation: Deleting agent policy ${ + newAgentPolicy.id + } and package policies ${createdPackagePolicyIds.join(', ')}` + ); + + // If there is an error creating package policies, delete any created package policy + // and the parent agent policy + const internalSOClient = appContextService.getInternalUserSOClient(); + const internalESClient = appContextService.getInternalUserESClient(); + + if (createdPackagePolicyIds.length > 0) { + await packagePolicyService.delete( + internalSOClient, + internalESClient, + createdPackagePolicyIds, + { + force: true, + skipUnassignFromAgentPolicies: true, + } + ); + } + await this.delete(internalSOClient, internalESClient, newAgentPolicy.id, { + force: true, + }); + + throw e; + } + } + public async requireUniqueName( soClient: SavedObjectsClientContract, givenPolicy: { id?: string; name: string; supports_agentless?: boolean | null } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.test.ts index aa85bbbf6c56d..e5b6ae84cafec 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.test.ts @@ -99,6 +99,7 @@ describe('createAgentPolicyWithPackages', () => { await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + agentPolicyService: mockedAgentPolicyService, newPolicy: { name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: true, spaceId: 'default', @@ -121,6 +122,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + agentPolicyService: mockedAgentPolicyService, newPolicy: { name: 'Fleet Server policy', namespace: 'default' }, hasFleetServer: true, withSysMonitoring: true, @@ -154,6 +156,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + agentPolicyService: mockedAgentPolicyService, newPolicy: { name: 'Fleet Server policy 2', namespace: 'default' }, hasFleetServer: true, withSysMonitoring: false, @@ -179,6 +182,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + agentPolicyService: mockedAgentPolicyService, newPolicy: { name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: true, spaceId: 'default', @@ -215,6 +219,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + agentPolicyService: mockedAgentPolicyService, newPolicy: { name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: true, spaceId: 'default', @@ -234,6 +239,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + agentPolicyService: mockedAgentPolicyService, newPolicy: { name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: true, spaceId: 'default', @@ -259,6 +265,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + agentPolicyService: mockedAgentPolicyService, newPolicy: { id: 'policy-1', name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: false, spaceId: 'default', @@ -272,6 +279,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + agentPolicyService: mockedAgentPolicyService, newPolicy: { id: 'policy-1', name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: false, spaceId: 'default', @@ -291,6 +299,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + agentPolicyService: mockedAgentPolicyService, newPolicy: { id: 'new_fleet_server_policy', name: 'Fleet Server policy', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.ts b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.ts index 07f93852356ae..f0d41cdb7739f 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.ts @@ -22,16 +22,15 @@ import { import type { AgentPolicy, NewAgentPolicy } from '../types'; -import { AgentlessAgentCreateOverProvisionnedError } from '../errors'; - -import { agentPolicyService, appContextService, packagePolicyService } from '.'; +import { type AgentPolicyServiceInterface, appContextService, packagePolicyService } from '.'; import { incrementPackageName } from './package_policies'; import { bulkInstallPackages } from './epm/packages'; import { ensureDefaultEnrollmentAPIKeyForAgentPolicy } from './api_keys'; import { agentlessAgentService } from './agents/agentless_agent'; async function getFleetServerAgentPolicyId( - soClient: SavedObjectsClientContract + soClient: SavedObjectsClientContract, + agentPolicyService: AgentPolicyServiceInterface ): Promise { const logger = appContextService.getLogger().get('getFleetServerAgentPolicyId'); @@ -65,6 +64,7 @@ async function getFleetServerAgentPolicyId( async function createPackagePolicy( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, + agentPolicyService: AgentPolicyServiceInterface, agentPolicy: AgentPolicy, packageToInstall: string, options: { @@ -106,6 +106,7 @@ async function createPackagePolicy( interface CreateAgentPolicyParams { soClient: SavedObjectsClientContract; esClient: ElasticsearchClient; + agentPolicyService: AgentPolicyServiceInterface; newPolicy: NewAgentPolicy; hasFleetServer?: boolean; withSysMonitoring: boolean; @@ -119,6 +120,7 @@ interface CreateAgentPolicyParams { export async function createAgentPolicyWithPackages({ soClient, esClient, + agentPolicyService, newPolicy, hasFleetServer, withSysMonitoring, @@ -141,7 +143,8 @@ export async function createAgentPolicyWithPackages({ if (hasFleetServer) { packagesToInstall.push(FLEET_SERVER_PACKAGE); - agentPolicyId = agentPolicyId || (await getFleetServerAgentPolicyId(soClient)); + agentPolicyId = + agentPolicyId || (await getFleetServerAgentPolicyId(soClient, agentPolicyService)); if (agentPolicyId === getDefaultFleetServerpolicyId(spaceId)) { // setting first fleet server policy to default, so that fleet server can enroll without setting policy_id @@ -179,22 +182,36 @@ export async function createAgentPolicyWithPackages({ // Create the fleet server package policy and add it to agent policy. if (hasFleetServer) { - await createPackagePolicy(soClient, esClient, agentPolicy, FLEET_SERVER_PACKAGE, { - spaceId, - user, - authorizationHeader, - force, - }); + await createPackagePolicy( + soClient, + esClient, + agentPolicyService, + agentPolicy, + FLEET_SERVER_PACKAGE, + { + spaceId, + user, + authorizationHeader, + force, + } + ); } // Create the system monitoring package policy and add it to agent policy. if (withSysMonitoring) { - await createPackagePolicy(soClient, esClient, agentPolicy, FLEET_SYSTEM_PACKAGE, { - spaceId, - user, - authorizationHeader, - force, - }); + await createPackagePolicy( + soClient, + esClient, + agentPolicyService, + agentPolicy, + FLEET_SYSTEM_PACKAGE, + { + spaceId, + user, + authorizationHeader, + force, + } + ); } await ensureDefaultEnrollmentAPIKeyForAgentPolicy(soClient, esClient, agentPolicy.id); @@ -205,13 +222,11 @@ export async function createAgentPolicyWithPackages({ try { await agentlessAgentService.createAgentlessAgent(esClient, soClient, agentPolicy); } catch (err) { - if (err instanceof AgentlessAgentCreateOverProvisionnedError) { - await agentPolicyService.delete(soClient, esClient, agentPolicy.id).catch((deleteError) => { - appContextService - .getLogger() - .error(`Error deleting agentless policy`, { error: agentPolicy }); - }); - } + await agentPolicyService.delete(soClient, esClient, agentPolicy.id).catch(() => { + appContextService + .getLogger() + .error(`Error deleting agentless policy`, { error: agentPolicy }); + }); throw err; } } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/index.ts b/x-pack/platform/plugins/shared/fleet/server/services/index.ts index 71710fc3bc88f..b7171101cdda3 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/index.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/index.ts @@ -16,6 +16,7 @@ export { getRegistryUrl } from './epm/registry/registry_url'; export interface AgentPolicyServiceInterface { create: (typeof agentPolicyService)['create']; + createWithPackagePolicies: (typeof agentPolicyService)['createWithPackagePolicies']; get: (typeof agentPolicyService)['get']; list: (typeof agentPolicyService)['list']; delete: (typeof agentPolicyService)['delete']; @@ -24,6 +25,7 @@ export interface AgentPolicyServiceInterface { turnOffAgentTamperProtections: (typeof agentPolicyService)['turnOffAgentTamperProtections']; fetchAllAgentPolicyIds: (typeof agentPolicyService)['fetchAllAgentPolicyIds']; fetchAllAgentPolicies: (typeof agentPolicyService)['fetchAllAgentPolicies']; + deployPolicy: (typeof agentPolicyService)['deployPolicy']; } // Agent services