Skip to content

Commit

Permalink
[Fleet] Handle invalid old package in getPackages (#162832)
Browse files Browse the repository at this point in the history
## Summary

Resolve #161768

Handle invalid old packages in the `getPackages` method, by ignoring and
logging a warning instead of crashing.

## Test

Tested by a unit test

How to manually reproduce? this can be reproduced by installing in 7.17
zscaler in version 0.1.2 then upgrade to 8.8.

---------

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
nchaulet and kibanamachine authored Aug 1, 2023
1 parent 6751324 commit 8683621
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 23 deletions.
77 changes: 77 additions & 0 deletions x-pack/plugins/fleet/server/services/epm/packages/get.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,83 @@ owner: elastic`,
]);
});

it('should filter installed package that are not in registry and not valid packages', async () => {
const mockContract = createAppContextStartContractMock();
appContextService.start(mockContract);

const soClient = savedObjectsClientMock.create();
soClient.find.mockResolvedValue({
saved_objects: [
{
id: 'invalidpackage',
attributes: {
name: 'invalidpackage',
version: '0.0.1',
install_source: 'upload',
install_version: '0.0.1',
},
},
],
} as any);
soClient.get.mockImplementation((type) => {
if (type === 'epm-packages-assets') {
return Promise.resolve({
attributes: {
data_utf8: `
name: invalidpackage
version: 0.0.1
test: invalid manifest`,
},
} as any);
} else {
return Promise.resolve({
id: 'invalidpackage',
attributes: {
name: 'invalidpackage',
version: '0.0.1',
install_source: 'upload',
package_assets: [],
data_utf8: `
name: invalidpackage
version: 0.0.1
title: Elastic
test: invalid manifest`,
},
});
}
});
soClient.bulkGet.mockResolvedValue({
saved_objects: [
{
id: 'test',
references: [],
type: 'epm-package-assets',
attributes: {
asset_path: 'invalidpackage-0.0.1/manifest.yml',
data_utf8: `
name: invalidpackage
version: 0.0.1
title: Elastic
test: invalid manifest
`,
},
},
],
});
const packages = await getPackages({
savedObjectsClient: soClient,
});
expect(packages).toMatchObject([
{ id: 'fleet_server', name: 'fleet_server', title: 'Fleet Server', version: '1.0.0' },
{ id: 'nginx', name: 'nginx', title: 'Nginx', version: '1.0.0' },
]);

expect(jest.mocked(appContextService.getLogger().warn)).toBeCalledTimes(1);
expect(jest.mocked(appContextService.getLogger().warn)).toBeCalledWith(
'Installed package invalidpackage 0.0.1 is not a valid package anymore'
);
});

it('should call audit logger', async () => {
const soClient = savedObjectsClientMock.create();

Expand Down
60 changes: 37 additions & 23 deletions x-pack/plugins/fleet/server/services/epm/packages/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
PackageFailedVerificationError,
PackageNotFoundError,
RegistryResponseError,
PackageInvalidArchiveError,
} from '../../../errors';
import { appContextService } from '../..';
import * as Registry from '../registry';
Expand Down Expand Up @@ -78,6 +79,7 @@ export async function getPackages(
excludeInstallStatus?: boolean;
} & GetPackagesRequest['query']
) {
const logger = appContextService.getLogger();
const {
savedObjectsClient,
category,
Expand All @@ -98,29 +100,41 @@ export async function getPackages(
(pkg) => !registryItems.some((item) => item.name === pkg.id)
);

const uploadedPackagesNotInRegistry = await pMap(
packagesNotInRegistry.entries(),
async ([i, pkg]) => {
// fetching info of uploaded packages to populate title, description
// limit to 10 for performance
if (i < MAX_PKGS_TO_LOAD_TITLE) {
const packageInfo = await withSpan({ name: 'get-package-info', type: 'package' }, () =>
getPackageInfo({
savedObjectsClient,
pkgName: pkg.id,
pkgVersion: pkg.attributes.version,
})
);
return createInstallableFrom({ ...packageInfo, id: pkg.id }, pkg);
} else {
return createInstallableFrom(
{ ...pkg.attributes, title: nameAsTitle(pkg.id), id: pkg.id },
pkg
);
}
},
{ concurrency: 10 }
);
const uploadedPackagesNotInRegistry = (
await pMap(
packagesNotInRegistry.entries(),
async ([i, pkg]) => {
// fetching info of uploaded packages to populate title, description
// limit to 10 for performance
if (i < MAX_PKGS_TO_LOAD_TITLE) {
try {
const packageInfo = await withSpan({ name: 'get-package-info', type: 'package' }, () =>
getPackageInfo({
savedObjectsClient,
pkgName: pkg.id,
pkgVersion: pkg.attributes.version,
})
);
return createInstallableFrom({ ...packageInfo, id: pkg.id }, pkg);
} catch (err) {
if (err instanceof PackageInvalidArchiveError) {
logger.warn(
`Installed package ${pkg.id} ${pkg.attributes.version} is not a valid package anymore`
);
return null;
}
throw err;
}
} else {
return createInstallableFrom(
{ ...pkg.attributes, title: nameAsTitle(pkg.id), id: pkg.id },
pkg
);
}
},
{ concurrency: 10 }
)
).filter((p): p is Installable<any> => p !== null);

const filteredPackages = getFilteredSearchPackages();
const packageList = registryItems
Expand Down

0 comments on commit 8683621

Please sign in to comment.