Skip to content

Commit

Permalink
[7.17] Add missing package policies for managed preconfigured policies
Browse files Browse the repository at this point in the history
  • Loading branch information
nchaulet authored and juliaElastic committed Feb 8, 2022
1 parent f170470 commit 5b62369
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 78 deletions.
8 changes: 6 additions & 2 deletions x-pack/plugins/fleet/server/services/agent_policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,8 @@ export async function addPackageToAgentPolicy(
packagePolicyName?: string,
packagePolicyId?: string | number,
packagePolicyDescription?: string,
transformPackagePolicy?: (p: NewPackagePolicy) => NewPackagePolicy
transformPackagePolicy?: (p: NewPackagePolicy) => NewPackagePolicy,
bumpAgentPolicyRevison = false
) {
const packageInfo = await getPackageInfo({
savedObjectsClient: soClient,
Expand Down Expand Up @@ -850,7 +851,10 @@ export async function addPackageToAgentPolicy(

await packagePolicyService.create(soClient, esClient, newPackagePolicy, {
id,
bumpRevision: false,
bumpRevision: bumpAgentPolicyRevison,
skipEnsureInstalled: true,
skipUniqueNameVerification: true,
overwrite: true,
force: true, // To add package to managed policy we need the force flag
});
}
19 changes: 12 additions & 7 deletions x-pack/plugins/fleet/server/services/package_policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,22 @@ class PackagePolicyService {
bumpRevision?: boolean;
force?: boolean;
skipEnsureInstalled?: boolean;
skipUniqueNameVerification?: boolean;
overwrite?: boolean;
}
): Promise<PackagePolicy> {
const existingPoliciesWithName = await this.list(soClient, {
perPage: 1,
kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.name: "${packagePolicy.name}"`,
});
if (!options?.skipUniqueNameVerification) {
const existingPoliciesWithName = await this.list(soClient, {
perPage: 1,
kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.name: "${packagePolicy.name}"`,
});

// Check that the name does not exist already
if (existingPoliciesWithName.items.length > 0) {
throw new IngestManagerError('There is already an integration policy with the same name');
// Check that the name does not exist already
if (existingPoliciesWithName.items.length > 0) {
throw new IngestManagerError('There is already an integration policy with the same name');
}
}

let elasticsearch: PackagePolicy['elasticsearch'];
// Add ids to stream
const packagePolicyId = options?.id || uuid.v4();
Expand Down
140 changes: 127 additions & 13 deletions x-pack/plugins/fleet/server/services/preconfiguration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
* 2.0.
*/

import uuid from 'uuid';
import { elasticsearchServiceMock, savedObjectsClientMock } from 'src/core/server/mocks';

import { SavedObjectsErrorHelpers } from '../../../../../src/core/server';

import type {
InstallResult,
PackagePolicy,
PreconfiguredAgentPolicy,
PreconfiguredOutput,
} from '../../common/types';
Expand All @@ -27,11 +29,13 @@ import {
cleanPreconfiguredOutputs,
} from './preconfiguration';
import { outputService } from './output';
import { packagePolicyService } from './package_policy';

jest.mock('./agent_policy_update');
jest.mock('./output');

const mockedOutputService = outputService as jest.Mocked<typeof outputService>;
const mockedPackagePolicyService = packagePolicyService as jest.Mocked<typeof packagePolicyService>;

const mockInstalledPackages = new Map();
const mockInstallPackageErrors = new Map<string, string>();
Expand All @@ -56,7 +60,7 @@ function getPutPreconfiguredPackagesMock() {
return {
saved_objects: [
{
id: `mocked-${id}`,
id,
attributes,
type: type as string,
score: 1,
Expand All @@ -79,8 +83,9 @@ function getPutPreconfiguredPackagesMock() {
soClient.get.mockImplementation(async (type, id) => {
const attributes = mockConfiguredPolicies.get(id);
if (!attributes) throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id);

return {
id: `mocked-${id}`,
id,
attributes,
type: type as string,
references: [],
Expand All @@ -91,7 +96,7 @@ function getPutPreconfiguredPackagesMock() {
const { id } = options!;
mockConfiguredPolicies.set(id, attributes);
return {
id: `mocked-${id}`,
id: id || uuid.v4(),
attributes,
type,
references: [],
Expand Down Expand Up @@ -162,13 +167,15 @@ jest.mock('./package_policy', () => ({
packagePolicyService: {
getByIDs: jest.fn().mockReturnValue([]),
listIds: jest.fn().mockReturnValue({ items: [] }),
create(soClient: any, esClient: any, newPackagePolicy: NewPackagePolicy) {
return {
id: 'mocked',
version: 'mocked',
...newPackagePolicy,
};
},
create: jest
.fn()
.mockImplementation((soClient: any, esClient: any, newPackagePolicy: NewPackagePolicy) => {
return {
id: 'mocked',
version: 'mocked',
...newPackagePolicy,
};
}),
get(soClient: any, id: string) {
return {
id: 'mocked',
Expand Down Expand Up @@ -200,6 +207,7 @@ const spyAgentPolicyServicBumpAllAgentPoliciesForOutput = jest.spyOn(

describe('policy preconfiguration', () => {
beforeEach(() => {
mockedPackagePolicyService.create.mockReset();
mockInstalledPackages.clear();
mockInstallPackageErrors.clear();
mockConfiguredPolicies.clear();
Expand Down Expand Up @@ -266,11 +274,116 @@ describe('policy preconfiguration', () => {
);

expect(policies.length).toEqual(1);
expect(policies[0].id).toBe('mocked-test-id');
expect(policies[0].id).toBe('test-id');
expect(packages).toEqual(expect.arrayContaining(['test_package-3.0.0']));
expect(nonFatalErrors.length).toBe(0);
});

it('should not add new package policy to existing non managed policies', async () => {
const soClient = getPutPreconfiguredPackagesMock();
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
mockedPackagePolicyService.getByIDs.mockResolvedValue([
{ name: 'test_package1' } as PackagePolicy,
]);

mockConfiguredPolicies.set('test-id', {
name: 'Test policy',
description: 'Test policy description',
unenroll_timeout: 120,
namespace: 'default',
id: 'test-id',
package_policies: [
{
name: 'test_package1',
},
],
} as PreconfiguredAgentPolicy);

await ensurePreconfiguredPackagesAndPolicies(
soClient,
esClient,
[
{
name: 'Test policy',
namespace: 'default',
id: 'test-id',
is_managed: false,
package_policies: [
{
package: { name: 'test_package' },
name: 'test_package1',
},
{
package: { name: 'test_package' },
name: 'test_package2',
},
],
},
] as PreconfiguredAgentPolicy[],
[{ name: 'test_package', version: '3.0.0' }],
mockDefaultOutput
);

expect(mockedPackagePolicyService.create).not.toBeCalled();
});

it('should add new package policy to existing managed policies', async () => {
const soClient = getPutPreconfiguredPackagesMock();
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
mockedPackagePolicyService.getByIDs.mockResolvedValue([
{ name: 'test_package1' } as PackagePolicy,
]);

mockConfiguredPolicies.set('test-id', {
name: 'Test policy',
description: 'Test policy description',
unenroll_timeout: 120,
namespace: 'default',
id: 'test-id',
package_policies: [
{
name: 'test_package1',
},
],
is_managed: true,
} as PreconfiguredAgentPolicy);

await ensurePreconfiguredPackagesAndPolicies(
soClient,
esClient,
[
{
name: 'Test policy',
namespace: 'default',
id: 'test-id',
is_managed: true,
package_policies: [
{
package: { name: 'test_package' },
name: 'test_package1',
},
{
package: { name: 'test_package' },
name: 'test_package2',
},
],
},
] as PreconfiguredAgentPolicy[],
[{ name: 'test_package', version: '3.0.0' }],
mockDefaultOutput
);

expect(mockedPackagePolicyService.create).toBeCalledTimes(1);
expect(mockedPackagePolicyService.create).toBeCalledWith(
expect.anything(), // so client
expect.anything(), // es client
expect.objectContaining({
name: 'test_package2',
}),
expect.anything() // options
);
});

it('should throw an error when trying to install duplicate packages', async () => {
const soClient = getPutPreconfiguredPackagesMock();
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
Expand Down Expand Up @@ -352,6 +465,7 @@ describe('policy preconfiguration', () => {
'[Test policy] could not be added. [test_package] is not installed, add [test_package] to [xpack.fleet.packages] or remove it from [Test package].'
);
});

it('should not attempt to recreate or modify an agent policy if its ID is unchanged', async () => {
const soClient = getPutPreconfiguredPackagesMock();
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
Expand All @@ -373,7 +487,7 @@ describe('policy preconfiguration', () => {
);

expect(policiesA.length).toEqual(1);
expect(policiesA[0].id).toBe('mocked-test-id');
expect(policiesA[0].id).toBe('test-id');
expect(nonFatalErrorsA.length).toBe(0);

const { policies: policiesB, nonFatalErrors: nonFatalErrorsB } =
Expand All @@ -398,7 +512,7 @@ describe('policy preconfiguration', () => {
);

expect(policiesB.length).toEqual(1);
expect(policiesB[0].id).toBe('mocked-test-id');
expect(policiesB[0].id).toBe('test-id');
expect(policiesB[0].updated_at).toEqual(policiesA[0].updated_at);
expect(nonFatalErrorsB.length).toBe(0);
});
Expand Down
Loading

0 comments on commit 5b62369

Please sign in to comment.