Skip to content

Commit a37e337

Browse files
connecting package policy to cloud connector with api integrations tests
1 parent 6e9c654 commit a37e337

File tree

12 files changed

+899
-22
lines changed

12 files changed

+899
-22
lines changed

x-pack/platform/plugins/shared/fleet/common/types/models/cloud_connector.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ export interface CloudConnectorVars {
3232
tenant_id?: CloudConnectorSecretVar;
3333
}
3434

35+
export type CloudConnectorVarsRecord = Record<string, PackagePolicyConfigRecordEntry | string | CloudConnectorSecretVar>;
36+
3537
export interface CloudConnectorSO {
3638
id: string;
3739
name: string;

x-pack/platform/plugins/shared/fleet/common/types/models/package_policy.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ export interface NewPackagePolicy {
9595
};
9696
overrides?: { inputs?: { [key: string]: any } } | null;
9797
supports_agentless?: boolean | null;
98+
supports_cloud_connector?: boolean | null;
99+
cloud_connector_id?: string | null;
98100
additional_datastreams_permissions?: string[];
99101
}
100102

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

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,4 +313,87 @@ describe('createAgentPolicyWithPackages', () => {
313313

314314
expect(response.id).toEqual('new_fleet_server_policy');
315315
});
316+
317+
it('should create agent policy with cloud connector enabled', async () => {
318+
const response = await createAgentPolicyWithPackages({
319+
esClient: esClientMock,
320+
soClient: soClientMock,
321+
agentPolicyService: mockedAgentPolicyService,
322+
newPolicy: {
323+
name: 'Agent policy with cloud connector',
324+
namespace: 'default',
325+
agentless: {
326+
cloud_connectors: {
327+
enabled: true,
328+
},
329+
},
330+
},
331+
withSysMonitoring: false,
332+
spaceId: 'default',
333+
monitoringEnabled: [],
334+
});
335+
336+
expect(response.id).toEqual('new_id');
337+
expect(response.agentless?.cloud_connectors?.enabled).toBe(true);
338+
});
339+
340+
it('should create agent policy with cloud connector disabled', async () => {
341+
const response = await createAgentPolicyWithPackages({
342+
esClient: esClientMock,
343+
soClient: soClientMock,
344+
agentPolicyService: mockedAgentPolicyService,
345+
newPolicy: {
346+
name: 'Agent policy without cloud connector',
347+
namespace: 'default',
348+
agentless: {
349+
cloud_connectors: {
350+
enabled: false,
351+
},
352+
},
353+
},
354+
withSysMonitoring: false,
355+
spaceId: 'default',
356+
monitoringEnabled: [],
357+
});
358+
359+
expect(response.id).toEqual('new_id');
360+
expect(response.agentless?.cloud_connectors?.enabled).toBe(false);
361+
});
362+
363+
it('should create package policy with cloud connector support when agent policy has cloud connector enabled', async () => {
364+
mockedPackagePolicyService.buildPackagePolicyFromPackage.mockImplementation(
365+
(soClient, packageToInstall) => Promise.resolve({
366+
...getPackagePolicy(packageToInstall),
367+
supports_cloud_connector: true,
368+
})
369+
);
370+
371+
const response = await createAgentPolicyWithPackages({
372+
esClient: esClientMock,
373+
soClient: soClientMock,
374+
agentPolicyService: mockedAgentPolicyService,
375+
newPolicy: {
376+
name: 'Agent policy with cloud connector',
377+
namespace: 'default',
378+
agentless: {
379+
cloud_connectors: {
380+
enabled: true,
381+
},
382+
},
383+
},
384+
withSysMonitoring: false,
385+
spaceId: 'default',
386+
monitoringEnabled: [],
387+
});
388+
389+
expect(response.id).toEqual('new_id');
390+
expect(mockedPackagePolicyService.create).toHaveBeenCalledWith(
391+
expect.anything(),
392+
expect.anything(),
393+
expect.objectContaining({
394+
supports_cloud_connector: true,
395+
}),
396+
expect.anything()
397+
);
398+
});
316399
});

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ async function createPackagePolicy(
9393
if (agentPolicy.supports_agentless) {
9494
newPackagePolicy.supports_agentless = agentPolicy.supports_agentless;
9595
}
96+
97+
// Check if agent policy supports cloud connectors
98+
if (agentPolicy.agentless?.cloud_connectors?.enabled) {
99+
newPackagePolicy.supports_cloud_connector = true;
100+
}
96101

97102
await packagePolicyService.create(soClient, esClient, newPackagePolicy, {
98103
spaceId: options.spaceId,

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

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ describe('CloudConnectorService', () => {
356356
});
357357
});
358358

359-
describe('extractCloudVars', () => {
359+
describe('getCloudConnectorInfo', () => {
360360
it('should extract AWS variables correctly', () => {
361361
const request: CreateCloudConnectorRequest = {
362362
name: 'test-connector',
@@ -376,8 +376,8 @@ describe('CloudConnectorService', () => {
376376
},
377377
};
378378

379-
const extractCloudVars = (service as any).extractCloudVars.bind(service);
380-
const result = extractCloudVars(request);
379+
const getCloudConnectorInfo = (service as any).getCloudConnectorInfo.bind(service);
380+
const result = getCloudConnectorInfo(request);
381381

382382
expect(result).toEqual({
383383
cloudProvider: 'aws',
@@ -414,8 +414,8 @@ describe('CloudConnectorService', () => {
414414
},
415415
};
416416

417-
const extractCloudVars = (service as any).extractCloudVars.bind(service);
418-
const result = extractCloudVars(request);
417+
const getCloudConnectorInfo = (service as any).getCloudConnectorInfo.bind(service);
418+
const result = getCloudConnectorInfo(request);
419419

420420
expect(result.vars.external_id).toEqual({
421421
type: 'password',
@@ -445,8 +445,8 @@ describe('CloudConnectorService', () => {
445445
},
446446
};
447447

448-
const extractCloudVars = (service as any).extractCloudVars.bind(service);
449-
const result = extractCloudVars(request);
448+
const getCloudConnectorInfo = (service as any).getCloudConnectorInfo.bind(service);
449+
const result = getCloudConnectorInfo(request);
450450

451451
expect(result.vars.external_id).toEqual({
452452
type: 'password',
@@ -476,9 +476,9 @@ describe('CloudConnectorService', () => {
476476
},
477477
};
478478

479-
const extractCloudVars = (service as any).extractCloudVars.bind(service);
479+
const getCloudConnectorInfo = (service as any).getCloudConnectorInfo.bind(service);
480480

481-
expect(() => extractCloudVars(request)).toThrow(
481+
expect(() => getCloudConnectorInfo(request)).toThrow(
482482
'[Cloud Connector API] External ID input var is not valid'
483483
);
484484
});
@@ -502,9 +502,9 @@ describe('CloudConnectorService', () => {
502502
},
503503
};
504504

505-
const extractCloudVars = (service as any).extractCloudVars.bind(service);
505+
const getCloudConnectorInfo = (service as any).getCloudConnectorInfo.bind(service);
506506

507-
expect(() => extractCloudVars(request)).toThrow(
507+
expect(() => getCloudConnectorInfo(request)).toThrow(
508508
'[Cloud Connector API] External ID input var is not valid'
509509
);
510510
});
@@ -528,9 +528,9 @@ describe('CloudConnectorService', () => {
528528
},
529529
};
530530

531-
const extractCloudVars = (service as any).extractCloudVars.bind(service);
531+
const getCloudConnectorInfo = (service as any).getCloudConnectorInfo.bind(service);
532532

533-
expect(() => extractCloudVars(request)).toThrow(
533+
expect(() => getCloudConnectorInfo(request)).toThrow(
534534
'[Cloud Connector API] External ID input var is not valid'
535535
);
536536
});
@@ -554,9 +554,9 @@ describe('CloudConnectorService', () => {
554554
},
555555
};
556556

557-
const extractCloudVars = (service as any).extractCloudVars.bind(service);
557+
const getCloudConnectorInfo = (service as any).getCloudConnectorInfo.bind(service);
558558

559-
expect(() => extractCloudVars(request)).toThrow(
559+
expect(() => getCloudConnectorInfo(request)).toThrow(
560560
'[Cloud Connector API] External ID input var is not valid'
561561
);
562562
});
@@ -580,8 +580,8 @@ describe('CloudConnectorService', () => {
580580
},
581581
};
582582

583-
const extractCloudVars = (service as any).extractCloudVars.bind(service);
584-
const result = extractCloudVars(request);
583+
const getCloudConnectorInfo = (service as any).getCloudConnectorInfo.bind(service);
584+
const result = getCloudConnectorInfo(request);
585585

586586
expect(result.vars.external_id).toEqual({
587587
type: 'password',
@@ -611,8 +611,8 @@ describe('CloudConnectorService', () => {
611611
},
612612
};
613613

614-
const extractCloudVars = (service as any).extractCloudVars.bind(service);
615-
const result = extractCloudVars(request);
614+
const getCloudConnectorInfo = (service as any).getCloudConnectorInfo.bind(service);
615+
const result = getCloudConnectorInfo(request);
616616

617617
expect(result.vars.external_id).toEqual({
618618
type: 'password',

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export interface CloudConnectorServiceInterface {
3232
): Promise<CloudConnectorSO[]>;
3333
}
3434

35+
3536
export class CloudConnectorService implements CloudConnectorServiceInterface {
3637
private static readonly EXTERNAL_ID_REGEX = /^[a-zA-Z0-9]{20}$/;
3738

@@ -52,7 +53,7 @@ export class CloudConnectorService implements CloudConnectorServiceInterface {
5253
logger.info('Creating cloud connector');
5354

5455
// Extract cloud variables from package policy
55-
const { cloudProvider, vars, name } = this.extractCloudVars(cloudConnector);
56+
const { cloudProvider, vars, name } = this.getCloudConnectorInfo(cloudConnector);
5657

5758
if (!vars || Object.keys(vars).length === 0) {
5859
logger.error(`Package policy must contain ${cloudProvider} input vars`);
@@ -130,7 +131,7 @@ export class CloudConnectorService implements CloudConnectorServiceInterface {
130131
}
131132
}
132133

133-
private extractCloudVars(cloudConnector: CreateCloudConnectorRequest): {
134+
private getCloudConnectorInfo(cloudConnector: CreateCloudConnectorRequest): {
134135
cloudProvider: CloudProvider;
135136
vars: CloudConnectorVars;
136137
name: string;

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

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,101 @@ describe('Package policy service', () => {
443443
id: 'b684f590-feeb-11ed-b202-b7f403f1dee9',
444444
});
445445
});
446+
447+
it('should handle cloud connector variables when supports_cloud_connector is true', async () => {
448+
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
449+
const soClient = createSavedObjectClientMock();
450+
451+
const packagePolicyWithCloudConnector = {
452+
name: 'test-package-policy',
453+
namespace: 'test',
454+
enabled: true,
455+
policy_id: 'test',
456+
policy_ids: ['test'],
457+
supports_cloud_connector: true,
458+
inputs: [
459+
{
460+
type: 'aws',
461+
enabled: true,
462+
vars: {
463+
'aws.role_arn': {
464+
value: 'arn:aws:iam::123456789012:role/TestRole',
465+
type: 'text',
466+
},
467+
'aws.credentials.external_id': {
468+
value: {
469+
id: 'ABCDEFGHIJKLMNOPQRST',
470+
isSecretRef: true,
471+
},
472+
type: 'password',
473+
},
474+
},
475+
},
476+
],
477+
};
478+
479+
soClient.bulkCreate.mockResolvedValueOnce({
480+
saved_objects: [
481+
{
482+
id: 'test-package-policy',
483+
attributes: packagePolicyWithCloudConnector,
484+
references: [],
485+
type: LEGACY_PACKAGE_POLICY_SAVED_OBJECT_TYPE,
486+
},
487+
],
488+
});
489+
490+
mockAgentPolicyGet();
491+
492+
const result = await packagePolicyService.create(soClient, esClient, packagePolicyWithCloudConnector);
493+
494+
expect(result.supports_cloud_connector).toBe(true);
495+
expect(result.inputs[0].vars).toHaveProperty('aws.role_arn');
496+
expect(result.inputs[0].vars).toHaveProperty('aws.credentials.external_id');
497+
});
498+
499+
it('should not process cloud connector variables when supports_cloud_connector is false', async () => {
500+
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
501+
const soClient = createSavedObjectClientMock();
502+
503+
const packagePolicyWithoutCloudConnector = {
504+
name: 'test-package-policy',
505+
namespace: 'test',
506+
enabled: true,
507+
policy_id: 'test',
508+
policy_ids: ['test'],
509+
supports_cloud_connector: false,
510+
inputs: [
511+
{
512+
type: 'aws',
513+
enabled: true,
514+
vars: {
515+
'aws.role_arn': {
516+
value: 'arn:aws:iam::123456789012:role/TestRole',
517+
type: 'text',
518+
},
519+
},
520+
},
521+
],
522+
};
523+
524+
soClient.bulkCreate.mockResolvedValueOnce({
525+
saved_objects: [
526+
{
527+
id: 'test-package-policy',
528+
attributes: packagePolicyWithoutCloudConnector,
529+
references: [],
530+
type: LEGACY_PACKAGE_POLICY_SAVED_OBJECT_TYPE,
531+
},
532+
],
533+
});
534+
535+
mockAgentPolicyGet();
536+
537+
const result = await packagePolicyService.create(soClient, esClient, packagePolicyWithoutCloudConnector);
538+
539+
expect(result.supports_cloud_connector).toBe(false);
540+
});
446541
});
447542

448543
describe('bulkCreate', () => {

0 commit comments

Comments
 (0)