Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1320,10 +1320,8 @@ class PackagePolicyClientImpl implements PackagePolicyClient {

for (const policyId of packagePolicyUpdate.policy_ids) {
const agentPolicy = await agentPolicyService.get(soClient, policyId, true);
if ((agentPolicy?.space_ids?.length ?? 0) > 1) {
throw new FleetError(
'Reusable integration policies cannot be used with agent policies belonging to multiple spaces.'
);
if (agentPolicy) {
validateReusableIntegrationsAndSpaceAwareness(packagePolicy, [agentPolicy]);
}

// Validate that if supports_agentless is true, the package actually supports agentless
Expand Down Expand Up @@ -1635,6 +1633,9 @@ class PackagePolicyClientImpl implements PackagePolicyClient {
internalSoClientWithoutSpaceExtension,
packagePolicy.policy_ids.map((policyId) => ({ id: policyId, spaceId: '*' }))
);

validateReusableIntegrationsAndSpaceAwareness(packagePolicy, agentPolicies);

if (!agentPolicies.some((policy) => policy.is_managed)) {
logger.debug(
`Saving previous revision of package policy ${id} with package version ${oldPackagePolicy.version}`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type {
GetOneAgentResponse,
GetOnePackagePolicyResponse,
GetPackagePoliciesResponse,
UpdatePackagePolicyResponse,
} from '@kbn/fleet-plugin/common';
import type {
GetEnrollmentAPIKeysResponse,
Expand Down Expand Up @@ -99,6 +100,29 @@ export class SpaceTestApiClient {
): Promise<CreatePackagePolicyResponse> {
const { body: res, statusCode } = await this.supertest
.post(`${this.getBaseUrl(spaceId)}/api/fleet/package_policies`)
.auth(this.auth.username, this.auth.password)
.set('kbn-xsrf', 'xxxx')
.send(data);

if (statusCode === 200) {
return res;
}

if (statusCode === 404) {
throw new Error('404 "Not Found"');
} else {
throw new Error(`${statusCode} "${res?.error}" ${res.message}`);
}
}

async updatePackagePolicy(
packagePolicyId: string,
data: Partial<SimplifiedPackagePolicy & { package: { name: string; version: string } }> = {},
spaceId?: string
): Promise<UpdatePackagePolicyResponse> {
const { body: res, statusCode } = await this.supertest
.put(`${this.getBaseUrl(spaceId)}/api/fleet/package_policies/${packagePolicyId}`)
.auth(this.auth.username, this.auth.password)
.set('kbn-xsrf', 'xxxx')
.send(data);

Expand All @@ -112,6 +136,25 @@ export class SpaceTestApiClient {
throw new Error(`${statusCode} "${res?.error}" ${res.message}`);
}
}

async deletePackagePolicy(packagePolicyId: string, spaceId?: string) {
const { body: res, statusCode } = await this.supertest
.delete(`${this.getBaseUrl(spaceId)}/api/fleet/package_policies/${packagePolicyId}`)
.auth(this.auth.username, this.auth.password)
.set('kbn-xsrf', 'xxxx')
.send();

if (statusCode === 200) {
return res;
}

if (statusCode === 404) {
throw new Error('404 "Not Found"');
} else {
throw new Error(`${statusCode} "${res?.error}" ${res.message}`);
}
}

async getPackagePolicy(
packagePolicyId: string,
spaceId?: string
Expand Down Expand Up @@ -450,6 +493,7 @@ export class SpaceTestApiClient {
) {
const { body: res } = await this.supertest
.post(`${this.getBaseUrl(spaceId)}/api/fleet/epm/packages/${pkgName}/${pkgVersion}`)
.auth(this.auth.username, this.auth.password)
.set('kbn-xsrf', 'xxxx')
.send({ force })
.expect(200);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,21 @@ export async function cleanFleetIndices(esClient: Client) {
q: '*',
ignore_unavailable: true,
refresh: true,
conflicts: 'proceed',
}),
esClient.deleteByQuery({
index: AGENTS_INDEX,
q: '*',
ignore_unavailable: true,
refresh: true,
conflicts: 'proceed',
}),
esClient.deleteByQuery({
index: AGENT_ACTIONS_INDEX,
q: '*',
ignore_unavailable: true,
refresh: true,
conflicts: 'proceed',
}),
]);
}
Expand All @@ -64,6 +67,7 @@ export async function cleanFleetAgents(esClient: Client) {
q: '*',
ignore_unavailable: true,
refresh: true,
conflicts: 'proceed',
});
}

Expand All @@ -73,6 +77,7 @@ export async function cleanFleetAgentPolicies(esClient: Client) {
q: '*',
refresh: true,
ignore_unavailable: true,
conflicts: 'proceed',
});
}

Expand All @@ -84,12 +89,14 @@ export async function cleanFleetActionIndices(esClient: Client) {
q: '*',
ignore_unavailable: true,
refresh: true,
conflicts: 'proceed',
}),
esClient.deleteByQuery(
{
index: AGENT_ACTIONS_RESULTS_INDEX,
q: '*',
refresh: true,
conflicts: 'proceed',
},
ES_INDEX_OPTIONS
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ export default function loadTests({ loadTestFile }) {
loadTestFile(require.resolve('./space_awareness_migration'));
loadTestFile(require.resolve('./telemetry'));
loadTestFile(require.resolve('./outputs'));
loadTestFile(require.resolve('./package_policies'));
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*
* 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 expect from '@kbn/expect';
import type { CreateAgentPolicyResponse } from '@kbn/fleet-plugin/common';
import type { FtrProviderContext } from '../../../api_integration/ftr_provider_context';
import { skipIfNoDockerRegistry } from '../../helpers';
import { SpaceTestApiClient } from './api_helper';
import { cleanFleetIndices, expectToRejectWithError } from './helpers';
import { setupTestUsers, testUsers } from '../test_users';

export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
const supertestWithoutAuth = getService('supertestWithoutAuth');
const esClient = getService('es');
const kibanaServer = getService('kibanaServer');
const spaces = getService('spaces');
let TEST_SPACE_1: string;

describe('package policies', function () {
skipIfNoDockerRegistry(providerContext);
const apiClient = new SpaceTestApiClient(supertestWithoutAuth, {
username: testUsers.fleet_all_int_all.username,
password: testUsers.fleet_all_int_all.password,
});

let multiSpacePolicy: CreateAgentPolicyResponse;
let defaultSpacePolicy: CreateAgentPolicyResponse;

before(async () => {
await setupTestUsers(getService('security'), true);
TEST_SPACE_1 = spaces.getDefaultTestSpace();
await kibanaServer.savedObjects.cleanStandardList();
await kibanaServer.savedObjects.cleanStandardList({
space: TEST_SPACE_1,
});
await cleanFleetIndices(esClient);

await apiClient.postEnableSpaceAwareness();

await spaces.createTestSpace(TEST_SPACE_1);
multiSpacePolicy = await apiClient.createAgentPolicy(undefined, {
space_ids: ['default', TEST_SPACE_1],
});
defaultSpacePolicy = await apiClient.createAgentPolicy(undefined, {
space_ids: ['default'],
});
await apiClient.installPackage({ pkgName: 'nginx', force: true, pkgVersion: '1.20.0' });
});

after(async () => {
await kibanaServer.savedObjects.cleanStandardList();
await kibanaServer.savedObjects.cleanStandardList({
space: TEST_SPACE_1,
});
await cleanFleetIndices(esClient);
});

describe('POST /package_policies', () => {
let packagePolicyId: string;
after(async () => {
if (packagePolicyId) {
await apiClient.deletePackagePolicy(packagePolicyId);
}
});
it('should allow to add a package policy to a multi-space agent policy in the default space', async () => {
const packagePolicyRes = await apiClient.createPackagePolicy(undefined, {
policy_ids: [multiSpacePolicy.item.id],
name: `test-nginx-${Date.now()}`,
description: 'test',
package: {
name: 'nginx',
version: '1.20.0',
},
inputs: {},
});

expect(packagePolicyRes.item).to.have.property('id');
packagePolicyId = packagePolicyRes.item.id;
});

it('should not allow to add a reusable package policy to a multi-space agent policy in the default space', async () => {
await expectToRejectWithError(
() =>
apiClient.createPackagePolicy(undefined, {
policy_ids: [multiSpacePolicy.item.id, defaultSpacePolicy.item.id],
name: `test-nginx-${Date.now()}`,
description: 'test',
package: {
name: 'nginx',
version: '1.20.0',
},
inputs: {},
}),
/400 "Bad Request" Reusable integration policies cannot be used with agent policies belonging to multiple spaces./
);
});
});

describe('PUT /package_policies', () => {
let packagePolicyId: string;
before(async () => {
const packagePolicyRes = await apiClient.createPackagePolicy(undefined, {
policy_ids: [multiSpacePolicy.item.id],
name: `test-nginx-${Date.now()}`,
description: 'test',
package: {
name: 'nginx',
version: '1.20.0',
},
inputs: {},
});
packagePolicyId = packagePolicyRes.item.id;
});
after(async () => {
if (packagePolicyId) {
await apiClient.deletePackagePolicy(packagePolicyId);
}
});
it('should allow to edit a package policy in a multi-space agent policy in the default space', async () => {
const packagePolicyRes = await apiClient.updatePackagePolicy(packagePolicyId, {
policy_ids: [multiSpacePolicy.item.id],
name: `test-nginx-${Date.now()}`,
description: 'test',
package: {
name: 'nginx',
version: '1.20.0',
},
inputs: {},
});

expect(packagePolicyRes.item).to.have.property('id');
packagePolicyId = packagePolicyRes.item.id;
});

it('should not allow to make a policy used in multiple space reusable', async () => {
await expectToRejectWithError(
() =>
apiClient.updatePackagePolicy(packagePolicyId, {
policy_ids: [multiSpacePolicy.item.id, defaultSpacePolicy.item.id],
name: `test-nginx-${Date.now()}`,
description: 'test',
package: {
name: 'nginx',
version: '1.20.0',
},
inputs: {},
}),
/400 "Bad Request" Reusable integration policies cannot be used with agent policies belonging to multiple spaces./
);
});
});
});
}
Loading