mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
# Backport This will backport the following commits from `main` to `8.x`: - [[Fleet] Reuse shared integration policies when duplicating agent policies (#217872)](https://github.com/elastic/kibana/pull/217872) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Jill Guyonnet","email":"jill.guyonnet@elastic.co"},"sourceCommit":{"committedDate":"2025-04-11T15:16:17Z","message":"[Fleet] Reuse shared integration policies when duplicating agent policies (#217872)\n\n## Summary\n\nCloses https://github.com/elastic/kibana/issues/215335\n\nCurrently, when an agent policy is duplicated, shared integration\npolicies are also duplicated. This PR adds logic where the duplicated\nagent policy also shares these integration policies.\n\n### Testing\n\n* Run ES with an [Entreprise\nlicense](https://www.elastic.co/subscriptions) to avail of reusable\nintegration policies.\n* Create an agent policy with a shared integration policy and a\nnon-shared integration policy.\n* Duplicate the agent policy: the duplicated policy should only\nduplicate the non-shared integration policy and the shared integration\npolicy should be reused.\n\n### Checklist\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [ ] The PR description includes the appropriate Release Notes section,\nand the correct `release_note:*` label is applied per the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\n\n### Identify risks\n\nIncorrect package policies in duplicated agent policies.","sha":"5c78ff18484e77b5ec5a4ba2ab341ed65db4f21c","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:enhancement","Team:Fleet","v9.0.0","backport:version","v9.1.0","v8.19.0"],"title":"[Fleet] Reuse shared integration policies when duplicating agent policies","number":217872,"url":"https://github.com/elastic/kibana/pull/217872","mergeCommit":{"message":"[Fleet] Reuse shared integration policies when duplicating agent policies (#217872)\n\n## Summary\n\nCloses https://github.com/elastic/kibana/issues/215335\n\nCurrently, when an agent policy is duplicated, shared integration\npolicies are also duplicated. This PR adds logic where the duplicated\nagent policy also shares these integration policies.\n\n### Testing\n\n* Run ES with an [Entreprise\nlicense](https://www.elastic.co/subscriptions) to avail of reusable\nintegration policies.\n* Create an agent policy with a shared integration policy and a\nnon-shared integration policy.\n* Duplicate the agent policy: the duplicated policy should only\nduplicate the non-shared integration policy and the shared integration\npolicy should be reused.\n\n### Checklist\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [ ] The PR description includes the appropriate Release Notes section,\nand the correct `release_note:*` label is applied per the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\n\n### Identify risks\n\nIncorrect package policies in duplicated agent policies.","sha":"5c78ff18484e77b5ec5a4ba2ab341ed65db4f21c"}},"sourceBranch":"main","suggestedTargetBranches":["9.0","8.x"],"targetPullRequestStates":[{"branch":"9.0","label":"v9.0.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/217872","number":217872,"mergeCommit":{"message":"[Fleet] Reuse shared integration policies when duplicating agent policies (#217872)\n\n## Summary\n\nCloses https://github.com/elastic/kibana/issues/215335\n\nCurrently, when an agent policy is duplicated, shared integration\npolicies are also duplicated. This PR adds logic where the duplicated\nagent policy also shares these integration policies.\n\n### Testing\n\n* Run ES with an [Entreprise\nlicense](https://www.elastic.co/subscriptions) to avail of reusable\nintegration policies.\n* Create an agent policy with a shared integration policy and a\nnon-shared integration policy.\n* Duplicate the agent policy: the duplicated policy should only\nduplicate the non-shared integration policy and the shared integration\npolicy should be reused.\n\n### Checklist\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [ ] The PR description includes the appropriate Release Notes section,\nand the correct `release_note:*` label is applied per the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\n\n### Identify risks\n\nIncorrect package policies in duplicated agent policies.","sha":"5c78ff18484e77b5ec5a4ba2ab341ed65db4f21c"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Jill Guyonnet <jill.guyonnet@elastic.co>
This commit is contained in:
parent
92623b406a
commit
df83efc556
2 changed files with 130 additions and 22 deletions
|
@ -1337,6 +1337,98 @@ describe('Agent policy', () => {
|
|||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should link shared package policies', async () => {
|
||||
agentPolicyService.requireUniqueName = async () => {};
|
||||
soClient = savedObjectsClientMock.create();
|
||||
const mockPolicy = {
|
||||
type: LEGACY_AGENT_POLICY_SAVED_OBJECT_TYPE,
|
||||
references: [],
|
||||
attributes: { revision: 1, package_policies: ['package-1'] } as any,
|
||||
};
|
||||
soClient.get.mockImplementation(async (type: string, id: string) => {
|
||||
return {
|
||||
id,
|
||||
...mockPolicy,
|
||||
};
|
||||
});
|
||||
soClient.find
|
||||
.mockImplementationOnce(async () => ({
|
||||
saved_objects: [
|
||||
{
|
||||
id: 'agent-policy-id',
|
||||
score: 1,
|
||||
...{ ...mockPolicy, name: 'mocked-policy' },
|
||||
},
|
||||
],
|
||||
total: 1,
|
||||
page: 1,
|
||||
per_page: 1,
|
||||
}))
|
||||
.mockImplementationOnce(async () => ({
|
||||
saved_objects: [
|
||||
{
|
||||
id: 'agent-policy-id-copy',
|
||||
score: 1,
|
||||
...{ ...mockPolicy, name: 'mocked-policy' },
|
||||
},
|
||||
],
|
||||
total: 1,
|
||||
page: 1,
|
||||
per_page: 1,
|
||||
}));
|
||||
soClient.create.mockImplementation(async (type, attributes) => {
|
||||
return {
|
||||
attributes: attributes as unknown as NewAgentPolicy,
|
||||
id: 'mocked',
|
||||
type: 'mocked',
|
||||
references: [],
|
||||
};
|
||||
});
|
||||
const packagePolicies = [
|
||||
{
|
||||
id: 'package-1',
|
||||
name: 'package-1',
|
||||
policy_id: 'policy_1',
|
||||
policy_ids: ['policy_1', 'policy_2'],
|
||||
},
|
||||
{
|
||||
id: 'package-2',
|
||||
name: 'package-2',
|
||||
policy_id: 'policy_1',
|
||||
policy_ids: ['policy_1'],
|
||||
},
|
||||
] as any;
|
||||
mockedPackagePolicyService.findAllForAgentPolicy.mockReturnValue(packagePolicies);
|
||||
mockedPackagePolicyService.list.mockResolvedValue({ items: packagePolicies } as any);
|
||||
await agentPolicyService.copy(soClient, esClient, 'mocked', {
|
||||
name: 'copy mocked',
|
||||
});
|
||||
expect(mockedPackagePolicyService.bulkCreate).toBeCalledWith(
|
||||
expect.anything(),
|
||||
expect.anything(),
|
||||
[
|
||||
{
|
||||
name: 'package-2 (copy)',
|
||||
policy_id: 'policy_1',
|
||||
policy_ids: ['mocked'],
|
||||
},
|
||||
],
|
||||
expect.anything()
|
||||
);
|
||||
expect(mockedPackagePolicyService.bulkUpdate).toBeCalledWith(
|
||||
expect.anything(),
|
||||
expect.anything(),
|
||||
[
|
||||
{
|
||||
id: 'package-1',
|
||||
name: 'package-1',
|
||||
policy_id: 'policy_1',
|
||||
policy_ids: ['policy_1', 'policy_2', 'mocked'],
|
||||
},
|
||||
]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('deployPolicy', () => {
|
||||
|
|
|
@ -831,32 +831,48 @@ class AgentPolicyService {
|
|||
options
|
||||
);
|
||||
|
||||
// Copy all package policies and append (copy n) to their names
|
||||
if (baseAgentPolicy.package_policies) {
|
||||
const newPackagePolicies = await pMap(
|
||||
baseAgentPolicy.package_policies as PackagePolicy[],
|
||||
async (packagePolicy: PackagePolicy) => {
|
||||
const { id: packagePolicyId, version, ...newPackagePolicy } = packagePolicy;
|
||||
// Copy non-shared package policies and append (copy n) to their names.
|
||||
const basePackagePolicies = baseAgentPolicy.package_policies.filter(
|
||||
(packagePolicy) => packagePolicy.policy_ids.length < 2
|
||||
);
|
||||
if (basePackagePolicies.length > 0) {
|
||||
const newPackagePolicies = await pMap(
|
||||
basePackagePolicies,
|
||||
async (packagePolicy: PackagePolicy) => {
|
||||
const { id: packagePolicyId, version, ...newPackagePolicy } = packagePolicy;
|
||||
|
||||
const updatedPackagePolicy = {
|
||||
const updatedPackagePolicy = {
|
||||
...newPackagePolicy,
|
||||
name: await incrementPackagePolicyCopyName(soClient, packagePolicy.name),
|
||||
};
|
||||
return updatedPackagePolicy;
|
||||
}
|
||||
);
|
||||
await packagePolicyService.bulkCreate(
|
||||
soClient,
|
||||
esClient,
|
||||
newPackagePolicies.map((newPackagePolicy) => ({
|
||||
...newPackagePolicy,
|
||||
name: await incrementPackagePolicyCopyName(soClient, packagePolicy.name),
|
||||
};
|
||||
return updatedPackagePolicy;
|
||||
}
|
||||
);
|
||||
await packagePolicyService.bulkCreate(
|
||||
soClient,
|
||||
esClient,
|
||||
newPackagePolicies.map((newPackagePolicy) => ({
|
||||
...newPackagePolicy,
|
||||
policy_ids: [newAgentPolicy.id],
|
||||
})),
|
||||
{
|
||||
...options,
|
||||
bumpRevision: false,
|
||||
}
|
||||
policy_ids: [newAgentPolicy.id],
|
||||
})),
|
||||
{
|
||||
...options,
|
||||
bumpRevision: false,
|
||||
}
|
||||
);
|
||||
}
|
||||
// Link shared package policies to new agent policy.
|
||||
const sharedBasePackagePolicies = baseAgentPolicy.package_policies.filter(
|
||||
(packagePolicy) => packagePolicy.policy_ids.length > 1
|
||||
);
|
||||
if (sharedBasePackagePolicies.length > 0) {
|
||||
const updatedSharedPackagePolicies = sharedBasePackagePolicies.map((packagePolicy) => ({
|
||||
...packagePolicy,
|
||||
policy_ids: [...packagePolicy.policy_ids, newAgentPolicy.id],
|
||||
}));
|
||||
await packagePolicyService.bulkUpdate(soClient, esClient, updatedSharedPackagePolicies);
|
||||
}
|
||||
}
|
||||
|
||||
// Tamper protection is dependent on endpoint package policy
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue