diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts index cd70b11aef305..483b3434d63f2 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts @@ -84,9 +84,15 @@ export class ManifestManagerMock extends ManifestManager { } export const getManifestManagerMock = (opts?: { + cache?: ExceptionsCache; packageConfigService?: PackageConfigServiceMock; savedObjectsClient?: ReturnType; }): ManifestManagerMock => { + let cache = new ExceptionsCache(5); + if (opts?.cache !== undefined) { + cache = opts.cache; + } + let packageConfigService = getPackageConfigServiceMock(); if (opts?.packageConfigService !== undefined) { packageConfigService = opts.packageConfigService; @@ -99,7 +105,7 @@ export const getManifestManagerMock = (opts?: { const manifestManager = new ManifestManagerMock({ artifactClient: getArtifactClientMock(savedObjectsClient), - cache: new ExceptionsCache(5), + cache, // @ts-ignore packageConfigService, exceptionListClient: listMock.getExceptionListClient(), diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts index ef4f921cb537e..900ad2c026956 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts @@ -5,7 +5,12 @@ */ import { savedObjectsClientMock } from 'src/core/server/mocks'; -import { ArtifactConstants, ManifestConstants, Manifest } from '../../../lib/artifacts'; +import { + ArtifactConstants, + ManifestConstants, + Manifest, + ExceptionsCache, +} from '../../../lib/artifacts'; import { getPackageConfigServiceMock, getManifestManagerMock } from './manifest_manager.mock'; describe('manifest_manager', () => { @@ -23,6 +28,43 @@ describe('manifest_manager', () => { expect(manifestWrapper!.manifest).toBeInstanceOf(Manifest); }); + test('ManifestManager populates cache properly', async () => { + const cache = new ExceptionsCache(5); + const manifestManager = getManifestManagerMock({ cache }); + const manifestWrapper = await manifestManager.refresh(); + expect(manifestWrapper!.diffs).toEqual([ + { + id: + 'endpoint-exceptionlist-linux-1.0.0-d34a1f6659bd86fc2023d7477aa2e5d2055c9c0fb0a0f10fae76bf8b94bebe49', + type: 'add', + }, + ]); + const diff = manifestWrapper!.diffs[0]; + const entry = JSON.parse(cache.get(diff!.id)!); + expect(entry).toEqual({ + exceptions_list: [ + { + entries: [ + { + field: 'nested.field', + operator: 'included', + type: 'exact_cased', + value: 'some value', + }, + ], + field: 'some.parentField', + type: 'nested', + }, + { + field: 'some.not.nested.field', + operator: 'included', + type: 'exact_cased', + value: 'some value', + }, + ], + }); + }); + test('ManifestManager can dispatch manifest', async () => { const packageConfigService = getPackageConfigServiceMock(); const manifestManager = getManifestManagerMock({ packageConfigService }); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts index 52887a38b3419..f7bc711d4bd05 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts @@ -139,6 +139,7 @@ export class ManifestManager { const artifact = newManifest.getArtifact(diff.id); try { await this.artifactClient.createArtifact(artifact); + // Cache the body of the artifact this.cache.set(diff.id, Buffer.from(artifact.body, 'base64').toString()); } catch (err) { diff --git a/x-pack/test/api_integration/apis/endpoint/artifacts/index.ts b/x-pack/test/api_integration/apis/endpoint/artifacts/index.ts index a63c2c19dc96c..3193a4456ba37 100644 --- a/x-pack/test/api_integration/apis/endpoint/artifacts/index.ts +++ b/x-pack/test/api_integration/apis/endpoint/artifacts/index.ts @@ -110,6 +110,61 @@ export default function (providerContext: FtrProviderContext) { }); }); + it('should download an artifact with correct hash from cache', async () => { + await supertestWithoutAuth + .get( + '/api/endpoint/artifacts/download/endpoint-exceptionlist-linux-1.0.0/d162f0302cbf419038ade7ea978e0a7ade7aad317fedefe455ff38dfa28b7cff' + ) + .set('kbn-xsrf', 'xxx') + .set('authorization', `ApiKey ${agentAccessAPIKey}`) + .send() + .expect(200) + .expect((response) => { + JSON.parse(response.text); + }) + .then(async () => { + await supertestWithoutAuth + .get( + '/api/endpoint/artifacts/download/endpoint-exceptionlist-linux-1.0.0/d162f0302cbf419038ade7ea978e0a7ade7aad317fedefe455ff38dfa28b7cff' + ) + .set('kbn-xsrf', 'xxx') + .set('authorization', `ApiKey ${agentAccessAPIKey}`) + .send() + .expect(200) + .expect((response) => { + const artifactJson = JSON.parse(response.text); + expect(artifactJson).to.eql({ + exceptions_list: [ + { + field: 'actingProcess.file.signer', + operator: 'included', + type: 'exact_cased', + value: 'Elastic, N.V.', + }, + { + entries: [ + { + field: 'signer', + operator: 'included', + type: 'exact_cased', + value: 'Evil', + }, + { + field: 'trusted', + operator: 'included', + type: 'exact_cased', + value: 'true', + }, + ], + field: 'file.signature', + type: 'nested', + }, + ], + }); + }); + }); + }); + it('should fail on invalid api key', async () => { await supertestWithoutAuth .get(