Skip to content

Commit

Permalink
[Security Solution] Fix showing integration status for single integra…
Browse files Browse the repository at this point in the history
…tion per package (#187200)

**Resolves:** #187199

## Summary

This PR fixes displaying related integration status for rules referring packages with a single integration. A good example is `Web Application Suspicious Activity: Unauthorized Method` rule which refers `APM` integration. Package and integration names don't match but the prebuilt rule only refers a package name omitting the integration name.

## Details

This fix changes response from `GET /internal/detection_engine/fleet/integrations/all` internal API endpoint by adding an additional integration for packages having a single integration which name doesn't match the package name.

For packages with a single integration and matching package and integration names there is only one integration returned with integration name and title omitted.

There are different packages with integrations

- a package with multiple integrations
- a package without integrations
- a package with only one integration which name matches with the package name
- a package with only one integration which name doesn't match with the package name

The latter case is `apm` package which has `apmServer` integration. For example `Web Application Suspicious Activity: Unauthorized Method` prebuilt rule specifies only `apm` package name which integration name is empty.

### Screenshots before

Installation rule preview popover:
<img width="1715" alt="image" src="https://github.com/elastic/kibana/assets/3775283/80f3d01f-5276-425b-835a-c78b69eab033">

Rule details page:
<img width="1722" alt="image" src="https://github.com/elastic/kibana/assets/3775283/85c833f9-b841-4016-8db9-43d4c68f1248">

### Screenshots after

Installation rule preview popover:
<img width="1718" alt="image" src="https://github.com/elastic/kibana/assets/3775283/a0ca1b4b-ebab-4de5-a169-1f6e55c74f35">

Rule details page:
<img width="1723" alt="image" src="https://github.com/elastic/kibana/assets/3775283/f647e536-2bc6-4ab8-8f4e-b4e923afb9ae">

Rule details page (Elastic APM integration is installed and enabled):
<img width="1718" alt="image" src="https://github.com/elastic/kibana/assets/3775283/33d12f7d-d9b9-43c3-9162-9bf7c6e015fc">
  • Loading branch information
maximpn authored Jul 15, 2024
1 parent 333cd20 commit 875d6e9
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,47 @@ describe('extractIntegrations', () => {
});

describe('for packages with only one policy template', () => {
it('extracts package title', () => {
it('extracts two integrations when package and integration names DO NOT match', () => {
const packages = [
{
name: 'package-a',
title: 'Package A',
version: '1.1.1',
policy_templates: [
{
name: 'integration-a',
title: 'Integration A',
},
],
},
] as PackageList;

const result = extractIntegrations(packages, []);

expect(result.length).toBe(2);
});

it('extracts one integration when package and integration names match', () => {
const packages = [
{
name: 'package-a',
title: 'Package A',
version: '1.1.1',
policy_templates: [
{
name: 'package-a',
title: 'Package A',
},
],
},
] as PackageList;

const result = extractIntegrations(packages, []);

expect(result.length).toBe(1);
});

it('extracts package title for both integrations', () => {
const packages = [
{
name: 'package-a',
Expand All @@ -325,6 +365,10 @@ describe('extractIntegrations', () => {
package_name: 'package-a',
package_title: 'Package A',
}),
expect.objectContaining({
package_name: 'package-a',
package_title: 'Package A',
}),
]);
});

Expand All @@ -345,15 +389,40 @@ describe('extractIntegrations', () => {

const result = extractIntegrations(packages, []);

expect(result).toEqual([
expect(result).toContainEqual(
expect.objectContaining({
integration_name: 'integration-a',
integration_title: 'Package A Integration a',
}),
]);
})
);
});

it('DOES NOT extract integration title for an extra integration', () => {
const packages = [
{
name: 'package-a',
title: 'Package A',
version: '1.1.1',
policy_templates: [
{
name: 'integration-a',
title: 'Integration A',
},
],
},
] as PackageList;

const result = extractIntegrations(packages, []);

expect(result).toEqual(
expect.not.objectContaining({
integration_name: expect.anything(),
integration_title: expect.anything(),
})
);
});

it('omits integration_name and integration_title are omitted when package and integration names match', () => {
it('omits integration_name and integration_title when package and integration names match', () => {
const packages = [
{
name: 'integration-a',
Expand Down Expand Up @@ -399,6 +468,9 @@ describe('extractIntegrations', () => {
expect.objectContaining({
latest_package_version: '1.1.1',
}),
expect.objectContaining({
latest_package_version: '1.1.1',
}),
]);
});

Expand All @@ -424,6 +496,10 @@ describe('extractIntegrations', () => {
is_installed: false,
is_enabled: false,
}),
expect.objectContaining({
is_installed: false,
is_enabled: false,
}),
]);
});

Expand Down Expand Up @@ -455,6 +531,10 @@ describe('extractIntegrations', () => {
is_installed: true,
is_enabled: false,
}),
expect.objectContaining({
is_installed: true,
is_enabled: false,
}),
]);
});

Expand Down Expand Up @@ -499,6 +579,10 @@ describe('extractIntegrations', () => {
is_installed: true,
is_enabled: true,
}),
expect.objectContaining({
is_installed: true,
is_enabled: true,
}),
]);
});

Expand Down Expand Up @@ -542,6 +626,9 @@ describe('extractIntegrations', () => {
expect.objectContaining({
installed_package_version: '1.0.0',
}),
expect.objectContaining({
installed_package_version: '1.0.0',
}),
]);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,36 @@ export function extractIntegrations(
const packagePolicyTemplates = fleetPackage.policy_templates ?? [];

for (const policyTemplate of packagePolicyTemplates) {
const integrationId = getIntegrationId(packageName, policyTemplate.name);
const integrationName = policyTemplate.name;
const integrationTitle =
packagePolicyTemplates.length === 1 && policyTemplate.name === fleetPackage.name
? packageTitle
: `${packageTitle} ${capitalize(policyTemplate.title)}`;

const integration: Integration = {
package_name: packageName,
package_title: packageTitle,
latest_package_version: fleetPackage.version,
installed_package_version: installedPackageVersion,
integration_name: packageName !== integrationName ? integrationName : undefined,
integration_title: packageName !== integrationName ? integrationTitle : undefined,
is_installed: isPackageInstalled, // All integrations installed as a part of the package
is_enabled: enabledIntegrationsSet.has(integrationId),
};
if (integrationName !== packageName) {
const integrationId = getIntegrationId(packageName, integrationName);
const integrationTitle = `${packageTitle} ${capitalize(policyTemplate.title)}`;
const integration: Integration = {
package_name: packageName,
package_title: packageTitle,
latest_package_version: fleetPackage.version,
installed_package_version: installedPackageVersion,
integration_name: integrationName,
integration_title: integrationTitle,
is_installed: isPackageInstalled, // All integrations installed as a part of the package
is_enabled: enabledIntegrationsSet.has(integrationId),
};

result.push(integration);
result.push(integration);
}
}

// some packages don't have policy templates at al, e.g. Lateral Movement Detection
if (packagePolicyTemplates.length === 0) {
// There are two edge cases here
//
// - (1) Some prebuilt rules don't use integration name when there is just
// one integration per package, e.g. "Web Application Suspicious Activity:
// Unauthorized Method" refers "apm" package name while apm package has
// "apmserver" integration
//
// - (2) Some packages don't have policy templates at all,
// e.g. "Lateral Movement Detection"
if (packagePolicyTemplates.length <= 1) {
result.push({
package_name: packageName,
package_title: packageTitle,
Expand Down

0 comments on commit 875d6e9

Please sign in to comment.