mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
Initial version of adding artifacts per policy to the manifest. (#89130)
* Initial version of adding artifacts per policy to the manifest. * Minor renaming to convey the purpose of the variable. * Added ability to override list item mock data. * Changed function signature to be more reusable. * Implementationg of support of artifacts per policy in the manifest data structure. * Added saved objects migrations. * Renamed the endpoint to reflect that it's artifacts endpoint. * Fixed tests. * Fixed the manifest data. * Fixed linting errors (result of merge). * Updated ES mappings for manifest in all test setups. * Updated hash in the mappings. * Fixed the typo that lead to failing test. * Fixed the problem with manifest not being dispatched to policies if there are same artifact names but different content. Artifact name in the ManifestSchema is not unique id, hence added decoded_sha256 to the comparison. Added test case to cover this. * Fixed the problem with the task flow when failure to dispatch to policies will result in commited manifest and no redispatch on next task run. Changed tests to reflect new flow (actually restored previous flow). * Forgot to commit changes in mock. * Made other tests more readable using same varialbe naming pattern. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
bcdc022efe
commit
e94a164b7e
47 changed files with 2748 additions and 1146 deletions
|
@ -31,7 +31,7 @@
|
|||
"core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724",
|
||||
"dashboard": "40554caf09725935e2c02e02563a2d07",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"enterprise_search_telemetry": "3d1b76c39bfb2cc8296b024d73854724",
|
||||
"epm-packages": "2b83397e3eaaaa8ef15e38813f3721c3",
|
||||
"exception-list": "67f055ab8c10abd7b2ebfd969b836788",
|
||||
|
@ -818,16 +818,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -22352,4 +22361,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,9 @@ import {
|
|||
|
||||
import { ExceptionListItemSchema } from './exception_list_item_schema';
|
||||
|
||||
export const getExceptionListItemSchemaMock = (): ExceptionListItemSchema => ({
|
||||
export const getExceptionListItemSchemaMock = (
|
||||
overrides?: Partial<ExceptionListItemSchema>
|
||||
): ExceptionListItemSchema => ({
|
||||
_version: undefined,
|
||||
comments: COMMENTS,
|
||||
created_at: DATE_NOW,
|
||||
|
@ -43,6 +45,7 @@ export const getExceptionListItemSchemaMock = (): ExceptionListItemSchema => ({
|
|||
type: ITEM_TYPE,
|
||||
updated_at: DATE_NOW,
|
||||
updated_by: USER,
|
||||
...(overrides || {}),
|
||||
});
|
||||
|
||||
export const getExceptionListItemSchemaXMock = (count = 1): ExceptionListItemSchema[] => {
|
||||
|
|
|
@ -11,10 +11,7 @@ import {
|
|||
policyFactory,
|
||||
policyFactoryWithoutPaidFeatures,
|
||||
} from '../../common/endpoint/models/policy_config';
|
||||
import {
|
||||
getManifestManagerMock,
|
||||
ManifestManagerMockType,
|
||||
} from './services/artifacts/manifest_manager/manifest_manager.mock';
|
||||
import { buildManifestManagerMock } from './services/artifacts/manifest_manager/manifest_manager.mock';
|
||||
import {
|
||||
getPackagePolicyCreateCallback,
|
||||
getPackagePolicyUpdateCallback,
|
||||
|
@ -32,6 +29,12 @@ import { ProtectionModes } from '../../common/endpoint/types';
|
|||
import type { SecuritySolutionRequestHandlerContext } from '../types';
|
||||
import { getExceptionListClientMock } from '../../../lists/server/services/exception_lists/exception_list_client.mock';
|
||||
import { ExceptionListClient } from '../../../lists/server';
|
||||
import { InternalArtifactCompleteSchema } from './schemas/artifacts';
|
||||
import { ManifestManager } from './services/artifacts/manifest_manager';
|
||||
import { getMockArtifacts, toArtifactRecords } from './lib/artifacts/mocks';
|
||||
import { Manifest } from './lib/artifacts';
|
||||
import { NewPackagePolicy } from '../../../fleet/common/types/models';
|
||||
import { ManifestSchema } from '../../common/endpoint/schema/manifest';
|
||||
|
||||
describe('ingest_integration tests ', () => {
|
||||
let endpointAppContextMock: EndpointAppContextServiceStartContract;
|
||||
|
@ -53,200 +56,182 @@ describe('ingest_integration tests ', () => {
|
|||
licenseService = new LicenseService();
|
||||
licenseService.start(licenseEmitter);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
licenseService.stop();
|
||||
licenseEmitter.complete();
|
||||
});
|
||||
|
||||
describe('ingest_integration sanity checks', () => {
|
||||
describe('package policy init callback (atifacts manifest initialisation tests)', () => {
|
||||
const createNewEndpointPolicyInput = (manifest: ManifestSchema) => ({
|
||||
type: 'endpoint',
|
||||
enabled: true,
|
||||
streams: [],
|
||||
config: {
|
||||
policy: { value: policyFactory() },
|
||||
artifact_manifest: { value: manifest },
|
||||
},
|
||||
});
|
||||
|
||||
const invokeCallback = async (manifestManager: ManifestManager): Promise<NewPackagePolicy> => {
|
||||
const logger = loggingSystemMock.create().get('ingest_integration.test');
|
||||
const callback = getPackagePolicyCreateCallback(
|
||||
logger,
|
||||
manifestManager,
|
||||
endpointAppContextMock.appClientFactory,
|
||||
maxTimelineImportExportSize,
|
||||
endpointAppContextMock.security,
|
||||
endpointAppContextMock.alerts,
|
||||
licenseService,
|
||||
exceptionListClient
|
||||
);
|
||||
|
||||
return callback(createNewPackagePolicyMock(), ctx, req);
|
||||
};
|
||||
|
||||
const TEST_POLICY_ID_1 = 'c6d16e42-c32d-4dce-8a88-113cfe276ad1';
|
||||
const TEST_POLICY_ID_2 = '93c46720-c217-11ea-9906-b5b8a21b268e';
|
||||
const ARTIFACT_NAME_EXCEPTIONS_MACOS = 'endpoint-exceptionlist-macos-v1';
|
||||
const ARTIFACT_NAME_TRUSTED_APPS_MACOS = 'endpoint-trustlist-macos-v1';
|
||||
const ARTIFACT_NAME_TRUSTED_APPS_WINDOWS = 'endpoint-trustlist-windows-v1';
|
||||
let ARTIFACT_EXCEPTIONS_MACOS: InternalArtifactCompleteSchema;
|
||||
let ARTIFACT_EXCEPTIONS_WINDOWS: InternalArtifactCompleteSchema;
|
||||
let ARTIFACT_TRUSTED_APPS_MACOS: InternalArtifactCompleteSchema;
|
||||
let ARTIFACT_TRUSTED_APPS_WINDOWS: InternalArtifactCompleteSchema;
|
||||
|
||||
beforeAll(async () => {
|
||||
const artifacts = await getMockArtifacts({ compress: true });
|
||||
ARTIFACT_EXCEPTIONS_MACOS = artifacts[0];
|
||||
ARTIFACT_EXCEPTIONS_WINDOWS = artifacts[1];
|
||||
ARTIFACT_TRUSTED_APPS_MACOS = artifacts[2];
|
||||
ARTIFACT_TRUSTED_APPS_WINDOWS = artifacts[3];
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
licenseEmitter.next(Platinum); // set license level to platinum
|
||||
});
|
||||
test('policy is updated with initial manifest', async () => {
|
||||
const logger = loggingSystemMock.create().get('ingest_integration.test');
|
||||
const manifestManager = getManifestManagerMock({
|
||||
mockType: ManifestManagerMockType.InitialSystemState,
|
||||
});
|
||||
|
||||
const callback = getPackagePolicyCreateCallback(
|
||||
logger,
|
||||
manifestManager,
|
||||
endpointAppContextMock.appClientFactory,
|
||||
maxTimelineImportExportSize,
|
||||
endpointAppContextMock.security,
|
||||
endpointAppContextMock.alerts,
|
||||
licenseService,
|
||||
exceptionListClient
|
||||
test('default manifest is taken when there is none and there are errors building new one', async () => {
|
||||
const manifestManager = buildManifestManagerMock();
|
||||
manifestManager.getLastComputedManifest = jest.fn().mockResolvedValue(null);
|
||||
manifestManager.buildNewManifest = jest.fn().mockRejectedValue(new Error());
|
||||
|
||||
expect((await invokeCallback(manifestManager)).inputs[0]).toStrictEqual(
|
||||
createNewEndpointPolicyInput({
|
||||
artifacts: {},
|
||||
manifest_version: '1.0.0',
|
||||
schema_version: 'v1',
|
||||
})
|
||||
);
|
||||
const policyConfig = createNewPackagePolicyMock(); // policy config without manifest
|
||||
const newPolicyConfig = await callback(policyConfig, ctx, req); // policy config WITH manifest
|
||||
|
||||
expect(newPolicyConfig.inputs[0]!.type).toEqual('endpoint');
|
||||
expect(newPolicyConfig.inputs[0]!.config!.policy.value).toEqual(policyFactory());
|
||||
expect(newPolicyConfig.inputs[0]!.config!.artifact_manifest.value).toEqual({
|
||||
artifacts: {
|
||||
'endpoint-exceptionlist-macos-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
decoded_sha256: 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
decoded_size: 14,
|
||||
encoded_sha256: 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
|
||||
encoded_size: 22,
|
||||
encryption_algorithm: 'none',
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-exceptionlist-macos-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
},
|
||||
'endpoint-exceptionlist-windows-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
decoded_sha256: 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
decoded_size: 14,
|
||||
encoded_sha256: 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
|
||||
encoded_size: 22,
|
||||
encryption_algorithm: 'none',
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-exceptionlist-windows-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
},
|
||||
'endpoint-trustlist-linux-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
decoded_sha256: '1a8295e6ccb93022c6f5ceb8997b29f2912389b3b38f52a8f5a2ff7b0154b1bc',
|
||||
decoded_size: 287,
|
||||
encoded_sha256: 'c3dec543df1177561ab2aa74a37997ea3c1d748d532a597884f5a5c16670d56c',
|
||||
encoded_size: 133,
|
||||
encryption_algorithm: 'none',
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-trustlist-linux-v1/1a8295e6ccb93022c6f5ceb8997b29f2912389b3b38f52a8f5a2ff7b0154b1bc',
|
||||
},
|
||||
'endpoint-trustlist-macos-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
decoded_sha256: '1a8295e6ccb93022c6f5ceb8997b29f2912389b3b38f52a8f5a2ff7b0154b1bc',
|
||||
decoded_size: 287,
|
||||
encoded_sha256: 'c3dec543df1177561ab2aa74a37997ea3c1d748d532a597884f5a5c16670d56c',
|
||||
encoded_size: 133,
|
||||
encryption_algorithm: 'none',
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-trustlist-macos-v1/1a8295e6ccb93022c6f5ceb8997b29f2912389b3b38f52a8f5a2ff7b0154b1bc',
|
||||
},
|
||||
'endpoint-trustlist-windows-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
decoded_sha256: '1a8295e6ccb93022c6f5ceb8997b29f2912389b3b38f52a8f5a2ff7b0154b1bc',
|
||||
decoded_size: 287,
|
||||
encoded_sha256: 'c3dec543df1177561ab2aa74a37997ea3c1d748d532a597884f5a5c16670d56c',
|
||||
encoded_size: 133,
|
||||
encryption_algorithm: 'none',
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-trustlist-windows-v1/1a8295e6ccb93022c6f5ceb8997b29f2912389b3b38f52a8f5a2ff7b0154b1bc',
|
||||
},
|
||||
},
|
||||
manifest_version: '1.0.0',
|
||||
schema_version: 'v1',
|
||||
});
|
||||
expect(manifestManager.buildNewManifest).toHaveBeenCalledWith();
|
||||
expect(manifestManager.pushArtifacts).not.toHaveBeenCalled();
|
||||
expect(manifestManager.commit).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('policy is returned even if error is encountered during artifact creation', async () => {
|
||||
const logger = loggingSystemMock.create().get('ingest_integration.test');
|
||||
const manifestManager = getManifestManagerMock();
|
||||
manifestManager.pushArtifacts = jest.fn().mockResolvedValue([new Error('error updating')]);
|
||||
const lastComputed = await manifestManager.getLastComputedManifest();
|
||||
test('default manifest is taken when there is none and there are errors pushing artifacts', async () => {
|
||||
const newManifest = Manifest.getDefault();
|
||||
newManifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
|
||||
const callback = getPackagePolicyCreateCallback(
|
||||
logger,
|
||||
manifestManager,
|
||||
endpointAppContextMock.appClientFactory,
|
||||
maxTimelineImportExportSize,
|
||||
endpointAppContextMock.security,
|
||||
endpointAppContextMock.alerts,
|
||||
licenseService,
|
||||
exceptionListClient
|
||||
);
|
||||
const policyConfig = createNewPackagePolicyMock();
|
||||
const newPolicyConfig = await callback(policyConfig, ctx, req);
|
||||
const manifestManager = buildManifestManagerMock();
|
||||
manifestManager.getLastComputedManifest = jest.fn().mockResolvedValue(null);
|
||||
manifestManager.buildNewManifest = jest.fn().mockResolvedValue(newManifest);
|
||||
manifestManager.pushArtifacts = jest.fn().mockResolvedValue([new Error()]);
|
||||
|
||||
expect(newPolicyConfig.inputs[0]!.type).toEqual('endpoint');
|
||||
expect(newPolicyConfig.inputs[0]!.config!.policy.value).toEqual(policyFactory());
|
||||
expect(newPolicyConfig.inputs[0]!.config!.artifact_manifest.value).toEqual(
|
||||
lastComputed!.toEndpointFormat()
|
||||
expect((await invokeCallback(manifestManager)).inputs[0]).toStrictEqual(
|
||||
createNewEndpointPolicyInput({
|
||||
artifacts: {},
|
||||
manifest_version: '1.0.0',
|
||||
schema_version: 'v1',
|
||||
})
|
||||
);
|
||||
|
||||
expect(manifestManager.buildNewManifest).toHaveBeenCalledWith();
|
||||
expect(manifestManager.pushArtifacts).toHaveBeenCalledWith([ARTIFACT_EXCEPTIONS_MACOS]);
|
||||
expect(manifestManager.commit).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('initial policy creation succeeds if manifest retrieval fails', async () => {
|
||||
const logger = loggingSystemMock.create().get('ingest_integration.test');
|
||||
const manifestManager = getManifestManagerMock({
|
||||
mockType: ManifestManagerMockType.InitialSystemState,
|
||||
});
|
||||
const lastComputed = await manifestManager.getLastComputedManifest();
|
||||
expect(lastComputed).toEqual(null);
|
||||
test('default manifest is taken when there is none and there are errors commiting manifest', async () => {
|
||||
const newManifest = Manifest.getDefault();
|
||||
newManifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
|
||||
manifestManager.buildNewManifest = jest.fn().mockRejectedValue(new Error('abcd'));
|
||||
const callback = getPackagePolicyCreateCallback(
|
||||
logger,
|
||||
manifestManager,
|
||||
endpointAppContextMock.appClientFactory,
|
||||
maxTimelineImportExportSize,
|
||||
endpointAppContextMock.security,
|
||||
endpointAppContextMock.alerts,
|
||||
licenseService,
|
||||
exceptionListClient
|
||||
const manifestManager = buildManifestManagerMock();
|
||||
manifestManager.getLastComputedManifest = jest.fn().mockResolvedValue(null);
|
||||
manifestManager.buildNewManifest = jest.fn().mockResolvedValue(newManifest);
|
||||
manifestManager.pushArtifacts = jest.fn().mockResolvedValue([]);
|
||||
manifestManager.commit = jest.fn().mockRejectedValue(new Error());
|
||||
|
||||
expect((await invokeCallback(manifestManager)).inputs[0]).toStrictEqual(
|
||||
createNewEndpointPolicyInput({
|
||||
artifacts: {},
|
||||
manifest_version: '1.0.0',
|
||||
schema_version: 'v1',
|
||||
})
|
||||
);
|
||||
const policyConfig = createNewPackagePolicyMock();
|
||||
const newPolicyConfig = await callback(policyConfig, ctx, req);
|
||||
|
||||
expect(newPolicyConfig.inputs[0]!.type).toEqual('endpoint');
|
||||
expect(newPolicyConfig.inputs[0]!.config!.policy.value).toEqual(policyFactory());
|
||||
expect(manifestManager.buildNewManifest).toHaveBeenCalledWith();
|
||||
expect(manifestManager.pushArtifacts).toHaveBeenCalledWith([ARTIFACT_EXCEPTIONS_MACOS]);
|
||||
expect(manifestManager.commit).toHaveBeenCalledWith(newManifest);
|
||||
});
|
||||
|
||||
test('subsequent policy creations succeed', async () => {
|
||||
const logger = loggingSystemMock.create().get('ingest_integration.test');
|
||||
const manifestManager = getManifestManagerMock();
|
||||
const lastComputed = await manifestManager.getLastComputedManifest();
|
||||
test('manifest is created successfuly when there is none', async () => {
|
||||
const newManifest = Manifest.getDefault();
|
||||
newManifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
newManifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS);
|
||||
|
||||
manifestManager.buildNewManifest = jest.fn().mockResolvedValue(lastComputed); // no diffs
|
||||
const callback = getPackagePolicyCreateCallback(
|
||||
logger,
|
||||
manifestManager,
|
||||
endpointAppContextMock.appClientFactory,
|
||||
maxTimelineImportExportSize,
|
||||
endpointAppContextMock.security,
|
||||
endpointAppContextMock.alerts,
|
||||
licenseService,
|
||||
exceptionListClient
|
||||
);
|
||||
const policyConfig = createNewPackagePolicyMock();
|
||||
const newPolicyConfig = await callback(policyConfig, ctx, req);
|
||||
const manifestManager = buildManifestManagerMock();
|
||||
manifestManager.getLastComputedManifest = jest.fn().mockResolvedValue(null);
|
||||
manifestManager.buildNewManifest = jest.fn().mockResolvedValue(newManifest);
|
||||
manifestManager.pushArtifacts = jest.fn().mockResolvedValue([]);
|
||||
manifestManager.commit = jest.fn().mockResolvedValue(null);
|
||||
|
||||
expect(newPolicyConfig.inputs[0]!.type).toEqual('endpoint');
|
||||
expect(newPolicyConfig.inputs[0]!.config!.policy.value).toEqual(policyFactory());
|
||||
expect(newPolicyConfig.inputs[0]!.config!.artifact_manifest.value).toEqual(
|
||||
lastComputed!.toEndpointFormat()
|
||||
expect((await invokeCallback(manifestManager)).inputs[0]).toStrictEqual(
|
||||
createNewEndpointPolicyInput({
|
||||
artifacts: toArtifactRecords({
|
||||
[ARTIFACT_NAME_EXCEPTIONS_MACOS]: ARTIFACT_EXCEPTIONS_MACOS,
|
||||
[ARTIFACT_NAME_TRUSTED_APPS_MACOS]: ARTIFACT_TRUSTED_APPS_MACOS,
|
||||
}),
|
||||
manifest_version: '1.0.0',
|
||||
schema_version: 'v1',
|
||||
})
|
||||
);
|
||||
|
||||
expect(manifestManager.buildNewManifest).toHaveBeenCalledWith();
|
||||
expect(manifestManager.pushArtifacts).toHaveBeenCalledWith([
|
||||
ARTIFACT_EXCEPTIONS_MACOS,
|
||||
ARTIFACT_TRUSTED_APPS_MACOS,
|
||||
]);
|
||||
expect(manifestManager.commit).toHaveBeenCalledWith(newManifest);
|
||||
});
|
||||
|
||||
test('policy creation succeeds even if endpoint exception list creation fails', async () => {
|
||||
const mockError = new Error('error creating endpoint list');
|
||||
const logger = loggingSystemMock.create().get('ingest_integration.test');
|
||||
const manifestManager = getManifestManagerMock();
|
||||
const lastComputed = await manifestManager.getLastComputedManifest();
|
||||
exceptionListClient.createEndpointList = jest.fn().mockRejectedValue(mockError);
|
||||
const callback = getPackagePolicyCreateCallback(
|
||||
logger,
|
||||
manifestManager,
|
||||
endpointAppContextMock.appClientFactory,
|
||||
maxTimelineImportExportSize,
|
||||
endpointAppContextMock.security,
|
||||
endpointAppContextMock.alerts,
|
||||
licenseService,
|
||||
exceptionListClient
|
||||
);
|
||||
const policyConfig = createNewPackagePolicyMock();
|
||||
const newPolicyConfig = await callback(policyConfig, ctx, req);
|
||||
test('policy is updated with only default entries from manifest', async () => {
|
||||
const manifest = new Manifest({ soVersion: '1.0.1', semanticVersion: '1.0.1' });
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_2);
|
||||
manifest.addEntry(ARTIFACT_TRUSTED_APPS_WINDOWS);
|
||||
|
||||
expect(exceptionListClient.createEndpointList).toHaveBeenCalled();
|
||||
expect(newPolicyConfig.inputs[0]!.type).toEqual('endpoint');
|
||||
expect(newPolicyConfig.inputs[0]!.config!.policy.value).toEqual(policyFactory());
|
||||
expect(newPolicyConfig.inputs[0]!.config!.artifact_manifest.value).toEqual(
|
||||
lastComputed!.toEndpointFormat()
|
||||
const manifestManager = buildManifestManagerMock();
|
||||
manifestManager.getLastComputedManifest = jest.fn().mockResolvedValue(manifest);
|
||||
|
||||
expect((await invokeCallback(manifestManager)).inputs[0]).toStrictEqual(
|
||||
createNewEndpointPolicyInput({
|
||||
artifacts: toArtifactRecords({
|
||||
[ARTIFACT_NAME_EXCEPTIONS_MACOS]: ARTIFACT_EXCEPTIONS_MACOS,
|
||||
[ARTIFACT_NAME_TRUSTED_APPS_WINDOWS]: ARTIFACT_TRUSTED_APPS_WINDOWS,
|
||||
}),
|
||||
manifest_version: '1.0.1',
|
||||
schema_version: 'v1',
|
||||
})
|
||||
);
|
||||
|
||||
expect(manifestManager.buildNewManifest).not.toHaveBeenCalled();
|
||||
expect(manifestManager.pushArtifacts).not.toHaveBeenCalled();
|
||||
expect(manifestManager.commit).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
describe('when the license is below platinum', () => {
|
||||
|
||||
describe('package policy update callback (when the license is below platinum)', () => {
|
||||
beforeEach(() => {
|
||||
licenseEmitter.next(Gold); // set license level to gold
|
||||
});
|
||||
|
@ -271,7 +256,8 @@ describe('ingest_integration tests ', () => {
|
|||
expect(updatedPolicyConfig.inputs[0]!.config!.policy.value).toEqual(mockPolicy);
|
||||
});
|
||||
});
|
||||
describe('when the license is at least platinum', () => {
|
||||
|
||||
describe('package policy update callback (when the license is at least platinum)', () => {
|
||||
beforeEach(() => {
|
||||
licenseEmitter.next(Platinum); // set license level to platinum
|
||||
});
|
||||
|
|
|
@ -39,37 +39,18 @@ const getManifest = async (logger: Logger, manifestManager: ManifestManager): Pr
|
|||
if (manifest == null) {
|
||||
// New computed manifest based on current state of exception list
|
||||
const newManifest = await manifestManager.buildNewManifest();
|
||||
const diffs = newManifest.diff(Manifest.getDefault());
|
||||
|
||||
// Compress new artifacts
|
||||
const adds = diffs.filter((diff) => diff.type === 'add').map((diff) => diff.id);
|
||||
for (const artifactId of adds) {
|
||||
const compressError = await newManifest.compressArtifact(artifactId);
|
||||
if (compressError) {
|
||||
throw compressError;
|
||||
}
|
||||
}
|
||||
|
||||
// Persist new artifacts
|
||||
const artifacts = adds
|
||||
.map((artifactId) => newManifest.getArtifact(artifactId))
|
||||
.filter((artifact): artifact is InternalArtifactCompleteSchema => artifact !== undefined);
|
||||
if (artifacts.length !== adds.length) {
|
||||
throw new Error('Invalid artifact encountered.');
|
||||
}
|
||||
const persistErrors = await manifestManager.pushArtifacts(artifacts);
|
||||
const persistErrors = await manifestManager.pushArtifacts(
|
||||
newManifest.getAllArtifacts() as InternalArtifactCompleteSchema[]
|
||||
);
|
||||
if (persistErrors.length) {
|
||||
reportErrors(logger, persistErrors);
|
||||
throw new Error('Unable to persist new artifacts.');
|
||||
}
|
||||
|
||||
// Commit the manifest state
|
||||
if (diffs.length) {
|
||||
const error = await manifestManager.commit(newManifest);
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
await manifestManager.commit(newManifest);
|
||||
|
||||
manifest = newManifest;
|
||||
}
|
||||
|
@ -93,7 +74,7 @@ export const getPackagePolicyCreateCallback = (
|
|||
licenseService: LicenseService,
|
||||
exceptionsClient: ExceptionListClient | undefined
|
||||
): ExternalCallback[1] => {
|
||||
const handlePackagePolicyCreate = async (
|
||||
return async (
|
||||
newPackagePolicy: NewPackagePolicy,
|
||||
context: RequestHandlerContext,
|
||||
request: KibanaRequest
|
||||
|
@ -143,7 +124,7 @@ export const getPackagePolicyCreateCallback = (
|
|||
|
||||
// Get most recent manifest
|
||||
const manifest = await getManifest(logger, manifestManager);
|
||||
const serializedManifest = manifest.toEndpointFormat();
|
||||
const serializedManifest = manifest.toPackagePolicyManifest();
|
||||
if (!manifestDispatchSchema.is(serializedManifest)) {
|
||||
// This should not happen.
|
||||
// But if it does, we log it and return it anyway.
|
||||
|
@ -183,15 +164,13 @@ export const getPackagePolicyCreateCallback = (
|
|||
|
||||
return updatedPackagePolicy;
|
||||
};
|
||||
|
||||
return handlePackagePolicyCreate;
|
||||
};
|
||||
|
||||
export const getPackagePolicyUpdateCallback = (
|
||||
logger: Logger,
|
||||
licenseService: LicenseService
|
||||
): ExternalCallback[1] => {
|
||||
const handlePackagePolicyUpdate = async (
|
||||
return async (
|
||||
newPackagePolicy: NewPackagePolicy,
|
||||
context: RequestHandlerContext,
|
||||
request: KibanaRequest
|
||||
|
@ -213,5 +192,4 @@ export const getPackagePolicyUpdateCallback = (
|
|||
}
|
||||
return newPackagePolicy;
|
||||
};
|
||||
return handlePackagePolicyUpdate;
|
||||
};
|
||||
|
|
|
@ -11,7 +11,6 @@ import { ExceptionListItemSchema } from '../../../../../lists/common/schemas';
|
|||
import { validate } from '../../../../common/validate';
|
||||
|
||||
import { Entry, EntryNested } from '../../../../../lists/common/schemas/types';
|
||||
import { FoundExceptionListItemSchema } from '../../../../../lists/common/schemas/response/found_exception_list_item_schema';
|
||||
import { ExceptionListClient } from '../../../../../lists/server';
|
||||
import { ENDPOINT_LIST_ID } from '../../../../common/shared_imports';
|
||||
import {
|
||||
|
@ -58,14 +57,14 @@ export async function maybeCompressArtifact(
|
|||
): Promise<InternalArtifactSchema> {
|
||||
const compressedArtifact = { ...uncompressedArtifact };
|
||||
if (internalArtifactCompleteSchema.is(uncompressedArtifact)) {
|
||||
const compressedExceptionList = await compressExceptionList(
|
||||
const compressedArtifactBody = await compressExceptionList(
|
||||
Buffer.from(uncompressedArtifact.body, 'base64')
|
||||
);
|
||||
compressedArtifact.body = compressedExceptionList.toString('base64');
|
||||
compressedArtifact.encodedSize = compressedExceptionList.byteLength;
|
||||
compressedArtifact.body = compressedArtifactBody.toString('base64');
|
||||
compressedArtifact.encodedSize = compressedArtifactBody.byteLength;
|
||||
compressedArtifact.compressionAlgorithm = 'zlib';
|
||||
compressedArtifact.encodedSha256 = createHash('sha256')
|
||||
.update(compressedExceptionList)
|
||||
.update(compressedArtifactBody)
|
||||
.digest('hex');
|
||||
}
|
||||
return compressedArtifact;
|
||||
|
@ -98,7 +97,7 @@ export async function getFullEndpointExceptionList(
|
|||
|
||||
if (response?.data !== undefined) {
|
||||
exceptions.entries = exceptions.entries.concat(
|
||||
translateToEndpointExceptions(response, schemaVersion)
|
||||
translateToEndpointExceptions(response.data, schemaVersion)
|
||||
);
|
||||
|
||||
paging = (page - 1) * 100 + response.data.length < response.total;
|
||||
|
@ -117,16 +116,17 @@ export async function getFullEndpointExceptionList(
|
|||
|
||||
/**
|
||||
* Translates Exception list items to Exceptions the endpoint can understand
|
||||
* @param exc
|
||||
* @param exceptions
|
||||
* @param schemaVersion
|
||||
*/
|
||||
export function translateToEndpointExceptions(
|
||||
exc: FoundExceptionListItemSchema,
|
||||
exceptions: ExceptionListItemSchema[],
|
||||
schemaVersion: string
|
||||
): TranslatedExceptionListItem[] {
|
||||
const entrySet = new Set();
|
||||
const entriesFiltered: TranslatedExceptionListItem[] = [];
|
||||
if (schemaVersion === 'v1') {
|
||||
exc.data.forEach((entry) => {
|
||||
exceptions.forEach((entry) => {
|
||||
const translatedItem = translateItem(schemaVersion, entry);
|
||||
const entryHash = createHash('sha256').update(JSON.stringify(translatedItem)).digest('hex');
|
||||
if (!entrySet.has(entryHash)) {
|
||||
|
|
|
@ -8,31 +8,48 @@
|
|||
import { ManifestSchemaVersion } from '../../../../common/endpoint/schema/common';
|
||||
import { InternalArtifactCompleteSchema } from '../../schemas';
|
||||
import { getArtifactId } from './common';
|
||||
import { Manifest } from './manifest';
|
||||
import {
|
||||
getMockArtifacts,
|
||||
getMockManifest,
|
||||
getMockManifestWithDiffs,
|
||||
getEmptyMockManifest,
|
||||
} from './mocks';
|
||||
import { isEmptyManifestDiff, Manifest } from './manifest';
|
||||
import { getMockArtifacts, toArtifactRecords } from './mocks';
|
||||
|
||||
describe('manifest', () => {
|
||||
describe('Manifest object sanity checks', () => {
|
||||
let artifacts: InternalArtifactCompleteSchema[] = [];
|
||||
let manifest1: Manifest;
|
||||
let manifest2: Manifest;
|
||||
let emptyManifest: Manifest;
|
||||
const TEST_POLICY_ID_1 = 'c6d16e42-c32d-4dce-8a88-113cfe276ad1';
|
||||
const TEST_POLICY_ID_2 = '93c46720-c217-11ea-9906-b5b8a21b268e';
|
||||
const ARTIFACT_ID_EXCEPTIONS_MACOS =
|
||||
'endpoint-exceptionlist-macos-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3';
|
||||
const ARTIFACT_ID_EXCEPTIONS_WINDOWS =
|
||||
'endpoint-exceptionlist-windows-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3';
|
||||
const ARTIFACT_ID_TRUSTED_APPS_MACOS =
|
||||
'endpoint-trustlist-macos-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3';
|
||||
const ARTIFACT_ID_TRUSTED_APPS_WINDOWS =
|
||||
'endpoint-trustlist-windows-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3';
|
||||
|
||||
beforeAll(async () => {
|
||||
artifacts = await getMockArtifacts({ compress: true });
|
||||
manifest1 = await getMockManifest({ compress: true });
|
||||
manifest2 = await getMockManifestWithDiffs({ compress: true });
|
||||
emptyManifest = await getEmptyMockManifest({ compress: true });
|
||||
});
|
||||
let ARTIFACTS: InternalArtifactCompleteSchema[] = [];
|
||||
let ARTIFACTS_COPY: InternalArtifactCompleteSchema[] = [];
|
||||
let ARTIFACT_EXCEPTIONS_MACOS: InternalArtifactCompleteSchema;
|
||||
let ARTIFACT_EXCEPTIONS_WINDOWS: InternalArtifactCompleteSchema;
|
||||
let ARTIFACT_TRUSTED_APPS_MACOS: InternalArtifactCompleteSchema;
|
||||
let ARTIFACT_TRUSTED_APPS_WINDOWS: InternalArtifactCompleteSchema;
|
||||
let ARTIFACT_COPY_EXCEPTIONS_MACOS: InternalArtifactCompleteSchema;
|
||||
let ARTIFACT_COPY_EXCEPTIONS_WINDOWS: InternalArtifactCompleteSchema;
|
||||
let ARTIFACT_COPY_TRUSTED_APPS_MACOS: InternalArtifactCompleteSchema;
|
||||
let ARTIFACT_COPY_TRUSTED_APPS_WINDOWS: InternalArtifactCompleteSchema;
|
||||
|
||||
beforeAll(async () => {
|
||||
ARTIFACTS = await getMockArtifacts({ compress: true });
|
||||
ARTIFACTS_COPY = await getMockArtifacts({ compress: true });
|
||||
ARTIFACT_EXCEPTIONS_MACOS = ARTIFACTS[0];
|
||||
ARTIFACT_EXCEPTIONS_WINDOWS = ARTIFACTS[1];
|
||||
ARTIFACT_TRUSTED_APPS_MACOS = ARTIFACTS[2];
|
||||
ARTIFACT_TRUSTED_APPS_WINDOWS = ARTIFACTS[3];
|
||||
ARTIFACT_COPY_EXCEPTIONS_MACOS = ARTIFACTS_COPY[0];
|
||||
ARTIFACT_COPY_EXCEPTIONS_WINDOWS = ARTIFACTS_COPY[1];
|
||||
ARTIFACT_COPY_TRUSTED_APPS_MACOS = ARTIFACTS_COPY[2];
|
||||
ARTIFACT_COPY_TRUSTED_APPS_WINDOWS = ARTIFACTS_COPY[3];
|
||||
});
|
||||
|
||||
describe('Manifest constructor', () => {
|
||||
test('Can create manifest with valid schema version', () => {
|
||||
const manifest = new Manifest();
|
||||
expect(manifest).toBeInstanceOf(Manifest);
|
||||
expect(new Manifest()).toBeInstanceOf(Manifest);
|
||||
});
|
||||
|
||||
test('Cannot create manifest with invalid schema version', () => {
|
||||
|
@ -43,177 +60,638 @@ describe('manifest', () => {
|
|||
}).toThrow();
|
||||
});
|
||||
|
||||
test('Empty manifest transforms correctly to expected endpoint format', async () => {
|
||||
expect(emptyManifest.toEndpointFormat()).toStrictEqual({
|
||||
artifacts: {
|
||||
'endpoint-exceptionlist-macos-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
encryption_algorithm: 'none',
|
||||
decoded_sha256: 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
encoded_sha256: 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
|
||||
decoded_size: 14,
|
||||
encoded_size: 22,
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-exceptionlist-macos-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
},
|
||||
'endpoint-exceptionlist-windows-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
encryption_algorithm: 'none',
|
||||
decoded_sha256: 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
encoded_sha256: 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
|
||||
decoded_size: 14,
|
||||
encoded_size: 22,
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-exceptionlist-windows-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
},
|
||||
},
|
||||
manifest_version: '1.0.0',
|
||||
schema_version: 'v1',
|
||||
test('Can create manifest with valid constructor parameters', () => {
|
||||
const manifest = new Manifest({
|
||||
schemaVersion: 'v1',
|
||||
semanticVersion: '1.1.1',
|
||||
soVersion: '2.2.2',
|
||||
});
|
||||
|
||||
expect(manifest.getAllArtifacts()).toStrictEqual([]);
|
||||
expect(manifest.getSchemaVersion()).toBe('v1');
|
||||
expect(manifest.getSemanticVersion()).toBe('1.1.1');
|
||||
expect(manifest.getSavedObjectVersion()).toBe('2.2.2');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Manifest.getDefault()', () => {
|
||||
test('Creates empty default manifest', () => {
|
||||
const manifest = Manifest.getDefault();
|
||||
|
||||
expect(manifest.getAllArtifacts()).toStrictEqual([]);
|
||||
expect(manifest.getSchemaVersion()).toBe('v1');
|
||||
expect(manifest.getSemanticVersion()).toBe('1.0.0');
|
||||
expect(manifest.getSavedObjectVersion()).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('bumpSemanticVersion', () => {
|
||||
test('Bumps the version properly', () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.1.1' });
|
||||
|
||||
manifest.bumpSemanticVersion();
|
||||
|
||||
expect(manifest.getSemanticVersion()).toBe('1.1.2');
|
||||
});
|
||||
});
|
||||
|
||||
describe('addEntry', () => {
|
||||
test('Adds default artifact', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
|
||||
expect(manifest.getAllArtifacts()).toStrictEqual([ARTIFACT_EXCEPTIONS_MACOS]);
|
||||
expect(manifest.isDefaultArtifact(ARTIFACT_EXCEPTIONS_MACOS)).toBe(true);
|
||||
expect(manifest.getArtifactTargetPolicies(ARTIFACT_EXCEPTIONS_MACOS)).toStrictEqual(
|
||||
new Set()
|
||||
);
|
||||
});
|
||||
|
||||
test('Adds policy specific artifact', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
|
||||
expect(manifest.getAllArtifacts()).toStrictEqual([ARTIFACT_EXCEPTIONS_MACOS]);
|
||||
expect(manifest.isDefaultArtifact(ARTIFACT_EXCEPTIONS_MACOS)).toBe(false);
|
||||
expect(manifest.getArtifactTargetPolicies(ARTIFACT_EXCEPTIONS_MACOS)).toStrictEqual(
|
||||
new Set([TEST_POLICY_ID_1])
|
||||
);
|
||||
});
|
||||
|
||||
test('Adds same artifact as default and policy specific', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
|
||||
expect(manifest.getAllArtifacts()).toStrictEqual([ARTIFACT_EXCEPTIONS_MACOS]);
|
||||
expect(manifest.isDefaultArtifact(ARTIFACT_EXCEPTIONS_MACOS)).toBe(true);
|
||||
expect(manifest.getArtifactTargetPolicies(ARTIFACT_EXCEPTIONS_MACOS)).toStrictEqual(
|
||||
new Set([TEST_POLICY_ID_1])
|
||||
);
|
||||
});
|
||||
|
||||
test('Adds multiple artifacts as default and policy specific', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_2);
|
||||
manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_2);
|
||||
manifest.addEntry(ARTIFACT_TRUSTED_APPS_WINDOWS);
|
||||
|
||||
expect(manifest.getAllArtifacts()).toStrictEqual(ARTIFACTS.slice(0, 4));
|
||||
expect(manifest.isDefaultArtifact(ARTIFACT_EXCEPTIONS_MACOS)).toBe(true);
|
||||
expect(manifest.isDefaultArtifact(ARTIFACT_EXCEPTIONS_WINDOWS)).toBe(false);
|
||||
expect(manifest.isDefaultArtifact(ARTIFACT_TRUSTED_APPS_MACOS)).toBe(true);
|
||||
expect(manifest.isDefaultArtifact(ARTIFACT_TRUSTED_APPS_WINDOWS)).toBe(true);
|
||||
expect(manifest.getArtifactTargetPolicies(ARTIFACT_EXCEPTIONS_MACOS)).toStrictEqual(
|
||||
new Set([TEST_POLICY_ID_1])
|
||||
);
|
||||
expect(manifest.getArtifactTargetPolicies(ARTIFACT_EXCEPTIONS_WINDOWS)).toStrictEqual(
|
||||
new Set([TEST_POLICY_ID_2])
|
||||
);
|
||||
expect(manifest.getArtifactTargetPolicies(ARTIFACT_TRUSTED_APPS_MACOS)).toStrictEqual(
|
||||
new Set([TEST_POLICY_ID_1, TEST_POLICY_ID_2])
|
||||
);
|
||||
expect(manifest.getArtifactTargetPolicies(ARTIFACT_TRUSTED_APPS_WINDOWS)).toStrictEqual(
|
||||
new Set([])
|
||||
);
|
||||
});
|
||||
|
||||
test('Adding same artifact as default multiple times has no effect', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
|
||||
expect(manifest.getAllArtifacts()).toStrictEqual(ARTIFACTS.slice(0, 1));
|
||||
expect(manifest.isDefaultArtifact(ARTIFACT_EXCEPTIONS_MACOS)).toBe(true);
|
||||
expect(manifest.getArtifactTargetPolicies(ARTIFACT_EXCEPTIONS_MACOS)).toStrictEqual(
|
||||
new Set([])
|
||||
);
|
||||
});
|
||||
|
||||
test('Adding same artifact as policy specific for same policy multiple times has no effect', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
|
||||
expect(manifest.getAllArtifacts()).toStrictEqual(ARTIFACTS.slice(0, 1));
|
||||
expect(manifest.isDefaultArtifact(ARTIFACT_EXCEPTIONS_MACOS)).toBe(false);
|
||||
expect(manifest.getArtifactTargetPolicies(ARTIFACT_EXCEPTIONS_MACOS)).toStrictEqual(
|
||||
new Set([TEST_POLICY_ID_1])
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAllArtifacts', () => {
|
||||
test('Returns empty list initially', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
expect(manifest.getAllArtifacts()).toStrictEqual([]);
|
||||
});
|
||||
|
||||
test('Returns only unique artifacts', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_2);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS);
|
||||
|
||||
expect(manifest.getAllArtifacts()).toStrictEqual(ARTIFACTS.slice(0, 2));
|
||||
});
|
||||
});
|
||||
|
||||
describe('getArtifact', () => {
|
||||
test('Returns undefined for non existing artifact id', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
|
||||
expect(manifest.getArtifact('non-existing-artifact-macos-v1')).toBeUndefined();
|
||||
});
|
||||
|
||||
test('Returns default artifact', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS);
|
||||
|
||||
expect(manifest.getArtifact(getArtifactId(ARTIFACT_EXCEPTIONS_MACOS))).toStrictEqual(
|
||||
ARTIFACT_EXCEPTIONS_MACOS
|
||||
);
|
||||
});
|
||||
|
||||
test('Returns policy specific artifact', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_2);
|
||||
|
||||
expect(manifest.getArtifact(getArtifactId(ARTIFACT_EXCEPTIONS_MACOS))).toStrictEqual(
|
||||
ARTIFACT_EXCEPTIONS_MACOS
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('containsArtifact', () => {
|
||||
test('Returns false for artifact that is not in the manifest', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
|
||||
expect(manifest.containsArtifact(ARTIFACT_EXCEPTIONS_WINDOWS)).toBe(false);
|
||||
});
|
||||
|
||||
test('Returns true for default artifact that is in the manifest', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS);
|
||||
|
||||
expect(manifest.containsArtifact(ARTIFACT_EXCEPTIONS_WINDOWS)).toBe(true);
|
||||
});
|
||||
|
||||
test('Returns true for policy specific artifact that is in the manifest', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_2);
|
||||
|
||||
expect(manifest.containsArtifact(ARTIFACT_EXCEPTIONS_WINDOWS)).toBe(true);
|
||||
});
|
||||
|
||||
test('Returns true for different instances but same ids', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
|
||||
expect(manifest.containsArtifact(ARTIFACT_COPY_EXCEPTIONS_MACOS)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isDefaultArtifact', () => {
|
||||
test('Returns undefined for artifact that is not in the manifest', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
|
||||
expect(manifest.isDefaultArtifact(ARTIFACT_EXCEPTIONS_WINDOWS)).toBeUndefined();
|
||||
});
|
||||
|
||||
test('Returns true for default artifact that is in the manifest', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
|
||||
expect(manifest.isDefaultArtifact(ARTIFACT_EXCEPTIONS_MACOS)).toBe(true);
|
||||
});
|
||||
|
||||
test('Returns false for policy specific artifact that is in the manifest', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
|
||||
expect(manifest.isDefaultArtifact(ARTIFACT_EXCEPTIONS_MACOS)).toBe(false);
|
||||
});
|
||||
|
||||
test('Returns true for different instances but same ids', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
|
||||
expect(manifest.isDefaultArtifact(ARTIFACT_COPY_EXCEPTIONS_MACOS)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getArtifactTargetPolicies', () => {
|
||||
test('Returns undefined for artifact that is not in the manifest', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
|
||||
expect(manifest.getArtifactTargetPolicies(ARTIFACT_EXCEPTIONS_WINDOWS)).toBeUndefined();
|
||||
});
|
||||
|
||||
test('Returns empty set for default artifact that is in the manifest', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
|
||||
expect(manifest.getArtifactTargetPolicies(ARTIFACT_EXCEPTIONS_MACOS)).toStrictEqual(
|
||||
new Set()
|
||||
);
|
||||
});
|
||||
|
||||
test('Returns policy set for policy specific artifact that is in the manifest', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_2);
|
||||
|
||||
expect(manifest.getArtifactTargetPolicies(ARTIFACT_EXCEPTIONS_MACOS)).toStrictEqual(
|
||||
new Set([TEST_POLICY_ID_1, TEST_POLICY_ID_2])
|
||||
);
|
||||
});
|
||||
|
||||
test('Returns policy set for different instances but same ids', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_2);
|
||||
|
||||
expect(manifest.getArtifactTargetPolicies(ARTIFACT_COPY_EXCEPTIONS_MACOS)).toStrictEqual(
|
||||
new Set([TEST_POLICY_ID_1, TEST_POLICY_ID_2])
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('diff', () => {
|
||||
test('Returns empty diff between empty manifests', async () => {
|
||||
expect(Manifest.getDefault().diff(Manifest.getDefault())).toStrictEqual({
|
||||
additions: [],
|
||||
removals: [],
|
||||
transitions: [],
|
||||
});
|
||||
});
|
||||
|
||||
test('Manifest transforms correctly to expected endpoint format', async () => {
|
||||
expect(manifest1.toEndpointFormat()).toStrictEqual({
|
||||
artifacts: {
|
||||
'endpoint-exceptionlist-macos-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
encryption_algorithm: 'none',
|
||||
decoded_sha256: '96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
encoded_sha256: '975382ab55d019cbab0bbac207a54e2a7d489fad6e8f6de34fc6402e5ef37b1e',
|
||||
decoded_size: 432,
|
||||
encoded_size: 147,
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-exceptionlist-macos-v1/96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
},
|
||||
'endpoint-exceptionlist-windows-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
encryption_algorithm: 'none',
|
||||
decoded_sha256: '96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
encoded_sha256: '975382ab55d019cbab0bbac207a54e2a7d489fad6e8f6de34fc6402e5ef37b1e',
|
||||
decoded_size: 432,
|
||||
encoded_size: 147,
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-exceptionlist-windows-v1/96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
},
|
||||
'endpoint-trustlist-linux-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
decoded_sha256: '96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
decoded_size: 432,
|
||||
encoded_sha256: '975382ab55d019cbab0bbac207a54e2a7d489fad6e8f6de34fc6402e5ef37b1e',
|
||||
encoded_size: 147,
|
||||
encryption_algorithm: 'none',
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-trustlist-linux-v1/96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
},
|
||||
'endpoint-trustlist-macos-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
decoded_sha256: '96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
decoded_size: 432,
|
||||
encoded_sha256: '975382ab55d019cbab0bbac207a54e2a7d489fad6e8f6de34fc6402e5ef37b1e',
|
||||
encoded_size: 147,
|
||||
encryption_algorithm: 'none',
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-trustlist-macos-v1/96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
},
|
||||
'endpoint-trustlist-windows-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
decoded_sha256: '96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
decoded_size: 432,
|
||||
encoded_sha256: '975382ab55d019cbab0bbac207a54e2a7d489fad6e8f6de34fc6402e5ef37b1e',
|
||||
encoded_size: 147,
|
||||
encryption_algorithm: 'none',
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-trustlist-windows-v1/96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
},
|
||||
},
|
||||
manifest_version: '1.0.0',
|
||||
schema_version: 'v1',
|
||||
test('Returns diff from empty manifest', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.1' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_2);
|
||||
|
||||
expect(manifest.diff(Manifest.getDefault())).toStrictEqual({
|
||||
additions: ARTIFACTS.slice(0, 3),
|
||||
removals: [],
|
||||
transitions: [],
|
||||
});
|
||||
});
|
||||
|
||||
test('Manifest transforms correctly to expected saved object format', async () => {
|
||||
expect(manifest1.toSavedObject()).toStrictEqual({
|
||||
test('Returns empty diff for equal manifests', async () => {
|
||||
const manifest1 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest1.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest1.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_2);
|
||||
manifest1.addEntry(ARTIFACT_TRUSTED_APPS_WINDOWS);
|
||||
manifest1.addEntry(ARTIFACT_TRUSTED_APPS_WINDOWS, TEST_POLICY_ID_2);
|
||||
|
||||
const manifest2 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.1' });
|
||||
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_MACOS);
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest2.addEntry(ARTIFACT_COPY_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest2.addEntry(ARTIFACT_COPY_TRUSTED_APPS_MACOS, TEST_POLICY_ID_2);
|
||||
manifest2.addEntry(ARTIFACT_COPY_TRUSTED_APPS_WINDOWS);
|
||||
manifest2.addEntry(ARTIFACT_COPY_TRUSTED_APPS_WINDOWS, TEST_POLICY_ID_2);
|
||||
|
||||
expect(manifest2.diff(manifest1)).toStrictEqual({
|
||||
additions: [],
|
||||
removals: [],
|
||||
transitions: [],
|
||||
});
|
||||
});
|
||||
|
||||
test('Returns additions diff properly', async () => {
|
||||
const manifest1 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
|
||||
const manifest2 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.1' });
|
||||
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_MACOS);
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest2.addEntry(ARTIFACT_COPY_TRUSTED_APPS_MACOS, TEST_POLICY_ID_2);
|
||||
manifest2.addEntry(ARTIFACT_COPY_TRUSTED_APPS_WINDOWS);
|
||||
|
||||
expect(manifest2.diff(manifest1)).toStrictEqual({
|
||||
additions: [ARTIFACT_COPY_TRUSTED_APPS_MACOS, ARTIFACT_COPY_TRUSTED_APPS_WINDOWS],
|
||||
removals: [],
|
||||
transitions: [],
|
||||
});
|
||||
});
|
||||
|
||||
test('Returns removals diff properly', async () => {
|
||||
const manifest1 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest1.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_2);
|
||||
manifest1.addEntry(ARTIFACT_TRUSTED_APPS_WINDOWS);
|
||||
|
||||
const manifest2 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.1' });
|
||||
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_MACOS);
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
|
||||
expect(manifest2.diff(manifest1)).toStrictEqual({
|
||||
additions: [],
|
||||
removals: [ARTIFACT_COPY_TRUSTED_APPS_MACOS, ARTIFACT_COPY_TRUSTED_APPS_WINDOWS],
|
||||
transitions: [],
|
||||
});
|
||||
});
|
||||
|
||||
test('Returns transitions from one policy to another in diff properly', async () => {
|
||||
const manifest1 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest1.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1);
|
||||
|
||||
const manifest2 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.1' });
|
||||
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_MACOS);
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
// policy transition
|
||||
manifest2.addEntry(ARTIFACT_COPY_TRUSTED_APPS_MACOS, TEST_POLICY_ID_2);
|
||||
|
||||
expect(manifest2.diff(manifest1)).toStrictEqual({
|
||||
additions: [],
|
||||
removals: [],
|
||||
transitions: [ARTIFACT_COPY_TRUSTED_APPS_MACOS],
|
||||
});
|
||||
});
|
||||
|
||||
test('Returns transitions from policy to default in diff properly', async () => {
|
||||
const manifest1 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest1.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1);
|
||||
|
||||
const manifest2 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.1' });
|
||||
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_MACOS);
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
// transition to default
|
||||
manifest2.addEntry(ARTIFACT_COPY_TRUSTED_APPS_MACOS);
|
||||
|
||||
expect(manifest2.diff(manifest1)).toStrictEqual({
|
||||
additions: [],
|
||||
removals: [],
|
||||
transitions: [ARTIFACT_COPY_TRUSTED_APPS_MACOS],
|
||||
});
|
||||
});
|
||||
|
||||
test('Returns transitions from default to specific policy in diff properly', async () => {
|
||||
const manifest1 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest1.addEntry(ARTIFACT_TRUSTED_APPS_MACOS);
|
||||
|
||||
const manifest2 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.1' });
|
||||
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_MACOS);
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
// transition to specific policy
|
||||
manifest2.addEntry(ARTIFACT_COPY_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1);
|
||||
|
||||
expect(manifest2.diff(manifest1)).toStrictEqual({
|
||||
additions: [],
|
||||
removals: [],
|
||||
transitions: [ARTIFACT_COPY_TRUSTED_APPS_MACOS],
|
||||
});
|
||||
});
|
||||
|
||||
test('Returns complex transitions diff properly', async () => {
|
||||
const manifest1 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest1.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest1.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_2);
|
||||
|
||||
const manifest2 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.1' });
|
||||
|
||||
// transition to default policy only
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_MACOS);
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
// transition to second policy
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_2);
|
||||
// transition to one policy only
|
||||
manifest2.addEntry(ARTIFACT_COPY_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1);
|
||||
|
||||
expect(manifest2.diff(manifest1)).toStrictEqual({
|
||||
additions: [],
|
||||
removals: [],
|
||||
transitions: ARTIFACTS_COPY.slice(0, 3),
|
||||
});
|
||||
});
|
||||
|
||||
test('Returns complex diff properly', async () => {
|
||||
const manifest1 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest1.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest1.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest1.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_2);
|
||||
manifest1.addEntry(ARTIFACT_TRUSTED_APPS_WINDOWS);
|
||||
|
||||
const manifest2 = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.1' });
|
||||
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_MACOS);
|
||||
manifest2.addEntry(ARTIFACT_COPY_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest2.addEntry(ARTIFACT_COPY_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1);
|
||||
|
||||
expect(manifest2.diff(manifest1)).toStrictEqual({
|
||||
additions: [ARTIFACT_COPY_EXCEPTIONS_WINDOWS],
|
||||
removals: [ARTIFACT_TRUSTED_APPS_WINDOWS],
|
||||
transitions: [ARTIFACT_COPY_EXCEPTIONS_MACOS, ARTIFACT_COPY_TRUSTED_APPS_MACOS],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('toPackagePolicyManifest', () => {
|
||||
test('Returns empty manifest', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
expect(manifest.toPackagePolicyManifest()).toStrictEqual({
|
||||
schema_version: 'v1',
|
||||
manifest_version: '1.0.0',
|
||||
artifacts: {},
|
||||
});
|
||||
});
|
||||
|
||||
test('Returns default policy manifest when no policy id provided', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1);
|
||||
|
||||
expect(manifest.toPackagePolicyManifest()).toStrictEqual({
|
||||
schema_version: 'v1',
|
||||
manifest_version: '1.0.0',
|
||||
artifacts: toArtifactRecords({
|
||||
'endpoint-exceptionlist-windows-v1': ARTIFACT_EXCEPTIONS_MACOS,
|
||||
'endpoint-exceptionlist-macos-v1': ARTIFACT_EXCEPTIONS_WINDOWS,
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
test('Returns default policy manifest when no policy specific artifacts present', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1);
|
||||
|
||||
expect(manifest.toPackagePolicyManifest(TEST_POLICY_ID_2)).toStrictEqual({
|
||||
schema_version: 'v1',
|
||||
manifest_version: '1.0.0',
|
||||
artifacts: toArtifactRecords({
|
||||
'endpoint-exceptionlist-windows-v1': ARTIFACT_EXCEPTIONS_MACOS,
|
||||
'endpoint-exceptionlist-macos-v1': ARTIFACT_EXCEPTIONS_WINDOWS,
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
test('Returns policy specific manifest when policy specific artifacts present', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1);
|
||||
|
||||
expect(manifest.toPackagePolicyManifest(TEST_POLICY_ID_2)).toStrictEqual({
|
||||
schema_version: 'v1',
|
||||
manifest_version: '1.0.0',
|
||||
artifacts: toArtifactRecords({
|
||||
'endpoint-exceptionlist-windows-v1': ARTIFACT_TRUSTED_APPS_MACOS,
|
||||
'endpoint-exceptionlist-macos-v1': ARTIFACT_EXCEPTIONS_WINDOWS,
|
||||
}),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('toSavedObject', () => {
|
||||
test('Returns empty saved object', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
expect(manifest.toSavedObject()).toStrictEqual({
|
||||
schemaVersion: 'v1',
|
||||
semanticVersion: '1.0.0',
|
||||
ids: [
|
||||
'endpoint-exceptionlist-macos-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
'endpoint-exceptionlist-windows-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
'endpoint-trustlist-macos-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
'endpoint-trustlist-windows-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
'endpoint-trustlist-linux-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
artifacts: [],
|
||||
});
|
||||
});
|
||||
|
||||
test('Returns populated saved object', async () => {
|
||||
const manifest = new Manifest({ schemaVersion: 'v1', semanticVersion: '1.0.0' });
|
||||
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS);
|
||||
manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_TRUSTED_APPS_WINDOWS, TEST_POLICY_ID_1);
|
||||
manifest.addEntry(ARTIFACT_TRUSTED_APPS_WINDOWS, TEST_POLICY_ID_2);
|
||||
|
||||
expect(manifest.toSavedObject()).toStrictEqual({
|
||||
schemaVersion: 'v1',
|
||||
semanticVersion: '1.0.0',
|
||||
artifacts: [
|
||||
{ artifactId: ARTIFACT_ID_EXCEPTIONS_MACOS, policyId: undefined },
|
||||
{ artifactId: ARTIFACT_ID_EXCEPTIONS_WINDOWS, policyId: undefined },
|
||||
{ artifactId: ARTIFACT_ID_EXCEPTIONS_WINDOWS, policyId: TEST_POLICY_ID_1 },
|
||||
{ artifactId: ARTIFACT_ID_TRUSTED_APPS_MACOS, policyId: TEST_POLICY_ID_1 },
|
||||
{ artifactId: ARTIFACT_ID_TRUSTED_APPS_WINDOWS, policyId: TEST_POLICY_ID_1 },
|
||||
{ artifactId: ARTIFACT_ID_TRUSTED_APPS_WINDOWS, policyId: TEST_POLICY_ID_2 },
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Manifest returns diffs since supplied manifest', async () => {
|
||||
const diffs = manifest2.diff(manifest1);
|
||||
expect(diffs).toEqual([
|
||||
{
|
||||
id:
|
||||
'endpoint-exceptionlist-macos-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
type: 'delete',
|
||||
},
|
||||
{
|
||||
id:
|
||||
'endpoint-trustlist-macos-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
type: 'delete',
|
||||
},
|
||||
{
|
||||
id:
|
||||
'endpoint-trustlist-windows-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
type: 'delete',
|
||||
},
|
||||
{
|
||||
id:
|
||||
'endpoint-trustlist-linux-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
type: 'delete',
|
||||
},
|
||||
{
|
||||
id:
|
||||
'endpoint-exceptionlist-macos-v1-0a5a2013a79f9e60682472284a1be45ab1ff68b9b43426d00d665016612c15c8',
|
||||
type: 'add',
|
||||
},
|
||||
]);
|
||||
describe('isEmptyManifestDiff', () => {
|
||||
test('Returns true when no additions, removals or transitions', async () => {
|
||||
expect(isEmptyManifestDiff({ additions: [], removals: [], transitions: [] })).toBe(true);
|
||||
});
|
||||
|
||||
test('Manifest returns data for given artifact', async () => {
|
||||
const artifact = artifacts[0];
|
||||
const returned = manifest1.getArtifact(getArtifactId(artifact));
|
||||
expect(returned).toEqual(artifact);
|
||||
test('Returns false when there are additions', async () => {
|
||||
const diff = { additions: [ARTIFACT_EXCEPTIONS_MACOS], removals: [], transitions: [] };
|
||||
|
||||
expect(isEmptyManifestDiff(diff)).toBe(false);
|
||||
});
|
||||
|
||||
test('Manifest returns entries map', async () => {
|
||||
const entries = manifest1.getEntries();
|
||||
const keys = Object.keys(entries);
|
||||
expect(keys).toEqual([
|
||||
'endpoint-exceptionlist-macos-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
'endpoint-exceptionlist-windows-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
'endpoint-trustlist-macos-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
'endpoint-trustlist-windows-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
'endpoint-trustlist-linux-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
]);
|
||||
test('Returns false when there are removals', async () => {
|
||||
const diff = { additions: [], removals: [ARTIFACT_EXCEPTIONS_MACOS], transitions: [] };
|
||||
|
||||
expect(isEmptyManifestDiff(diff)).toBe(false);
|
||||
});
|
||||
|
||||
test('Manifest returns true if contains artifact', async () => {
|
||||
const found = manifest1.contains(
|
||||
'endpoint-exceptionlist-macos-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3'
|
||||
);
|
||||
expect(found).toEqual(true);
|
||||
test('Returns false when there are transitions', async () => {
|
||||
const diff = { additions: [], removals: [], transitions: [ARTIFACT_EXCEPTIONS_MACOS] };
|
||||
|
||||
expect(isEmptyManifestDiff(diff)).toBe(false);
|
||||
});
|
||||
|
||||
test('Manifest can be created from list of artifacts', async () => {
|
||||
const oldManifest = new Manifest();
|
||||
const manifest = Manifest.fromArtifacts(artifacts, oldManifest);
|
||||
expect(
|
||||
manifest.contains(
|
||||
'endpoint-exceptionlist-macos-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3'
|
||||
)
|
||||
).toEqual(true);
|
||||
expect(
|
||||
manifest.contains(
|
||||
'endpoint-exceptionlist-windows-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3'
|
||||
)
|
||||
).toEqual(true);
|
||||
test('Returns false when there are all typesof changes', async () => {
|
||||
const diff = {
|
||||
additions: [ARTIFACT_EXCEPTIONS_MACOS],
|
||||
removals: [ARTIFACT_EXCEPTIONS_WINDOWS],
|
||||
transitions: [ARTIFACT_TRUSTED_APPS_MACOS],
|
||||
};
|
||||
|
||||
expect(isEmptyManifestDiff(diff)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { flatMap, isEqual } from 'lodash';
|
||||
import semver from 'semver';
|
||||
import { validate } from '../../../../common/validate';
|
||||
import { validate } from '../../../../common';
|
||||
import {
|
||||
InternalArtifactSchema,
|
||||
InternalManifestSchema,
|
||||
internalArtifactCompleteSchema,
|
||||
InternalArtifactCompleteSchema,
|
||||
InternalManifestEntrySchema,
|
||||
} from '../../schemas/artifacts';
|
||||
import {
|
||||
ManifestSchemaVersion,
|
||||
|
@ -20,21 +20,46 @@ import {
|
|||
} from '../../../../common/endpoint/schema/common';
|
||||
import { manifestSchema, ManifestSchema } from '../../../../common/endpoint/schema/manifest';
|
||||
import { ManifestEntry } from './manifest_entry';
|
||||
import { maybeCompressArtifact, isCompressed } from './lists';
|
||||
import { getArtifactId } from './common';
|
||||
import { ManifestVersion, manifestVersion } from '../../schemas/artifacts/manifest';
|
||||
|
||||
function createInternalManifestEntries(
|
||||
artifactIds: string[],
|
||||
policyId?: string
|
||||
): InternalManifestEntrySchema[] {
|
||||
return artifactIds.map((artifactId) => ({ policyId, artifactId }));
|
||||
}
|
||||
|
||||
export interface ManifestDiff {
|
||||
type: string;
|
||||
id: string;
|
||||
additions: InternalArtifactSchema[];
|
||||
removals: InternalArtifactSchema[];
|
||||
transitions: InternalArtifactSchema[];
|
||||
}
|
||||
|
||||
export function isEmptyManifestDiff(diff: ManifestDiff) {
|
||||
return diff.additions.length === 0 && diff.removals.length === 0 && diff.transitions.length === 0;
|
||||
}
|
||||
|
||||
interface ManifestEntryDescriptor {
|
||||
isDefaultEntry: boolean;
|
||||
specificTargetPolicies: Set<string>;
|
||||
entry: ManifestEntry;
|
||||
}
|
||||
|
||||
function addValueToSet<T>(set?: Set<T>, value?: T) {
|
||||
return new Set([...(set?.values() || []), ...(value !== undefined ? [value] : [])]);
|
||||
}
|
||||
|
||||
export class Manifest {
|
||||
private entries: Record<string, ManifestEntry>;
|
||||
private readonly allEntries: Map<string, ManifestEntryDescriptor>;
|
||||
private readonly defaultEntries: Map<string, ManifestEntry>;
|
||||
private readonly policySpecificEntries: Map<string, Map<string, ManifestEntry>>;
|
||||
private version: ManifestVersion;
|
||||
|
||||
constructor(version?: Partial<ManifestVersion>) {
|
||||
this.entries = {};
|
||||
this.allEntries = new Map();
|
||||
this.defaultEntries = new Map();
|
||||
this.policySpecificEntries = new Map();
|
||||
|
||||
const decodedVersion = {
|
||||
schemaVersion: version?.schemaVersion ?? 'v1',
|
||||
|
@ -54,28 +79,6 @@ export class Manifest {
|
|||
return new Manifest({ schemaVersion, semanticVersion: '1.0.0' });
|
||||
}
|
||||
|
||||
public static fromArtifacts(
|
||||
artifacts: InternalArtifactCompleteSchema[],
|
||||
oldManifest: Manifest,
|
||||
schemaVersion?: ManifestSchemaVersion
|
||||
): Manifest {
|
||||
const manifest = new Manifest({
|
||||
schemaVersion,
|
||||
semanticVersion: oldManifest.getSemanticVersion(),
|
||||
soVersion: oldManifest.getSavedObjectVersion(),
|
||||
});
|
||||
artifacts.forEach((artifact) => {
|
||||
const id = getArtifactId(artifact);
|
||||
const existingArtifact = oldManifest.getArtifact(id);
|
||||
if (existingArtifact) {
|
||||
manifest.addEntry(existingArtifact);
|
||||
} else {
|
||||
manifest.addEntry(artifact);
|
||||
}
|
||||
});
|
||||
return manifest;
|
||||
}
|
||||
|
||||
public bumpSemanticVersion() {
|
||||
const newSemanticVersion = semver.inc(this.getSemanticVersion(), 'patch');
|
||||
if (!semanticVersion.is(newSemanticVersion)) {
|
||||
|
@ -84,26 +87,6 @@ export class Manifest {
|
|||
this.version.semanticVersion = newSemanticVersion;
|
||||
}
|
||||
|
||||
public async compressArtifact(id: string): Promise<Error | null> {
|
||||
try {
|
||||
const artifact = this.getArtifact(id);
|
||||
if (artifact == null) {
|
||||
throw new Error(`Corrupted manifest detected. Artifact ${id} not in manifest.`);
|
||||
}
|
||||
|
||||
const compressedArtifact = await maybeCompressArtifact(artifact);
|
||||
if (!isCompressed(compressedArtifact)) {
|
||||
throw new Error(`Unable to compress artifact: ${id}`);
|
||||
} else if (!internalArtifactCompleteSchema.is(compressedArtifact)) {
|
||||
throw new Error(`Incomplete artifact detected: ${id}`);
|
||||
}
|
||||
this.addEntry(compressedArtifact);
|
||||
} catch (err) {
|
||||
return err;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public getSchemaVersion(): ManifestSchemaVersion {
|
||||
return this.version.schemaVersion;
|
||||
}
|
||||
|
@ -116,53 +99,85 @@ export class Manifest {
|
|||
return this.version.semanticVersion;
|
||||
}
|
||||
|
||||
public addEntry(artifact: InternalArtifactSchema) {
|
||||
const entry = new ManifestEntry(artifact);
|
||||
this.entries[entry.getDocId()] = entry;
|
||||
public addEntry(artifact: InternalArtifactSchema, policyId?: string) {
|
||||
const existingDescriptor = this.allEntries.get(getArtifactId(artifact));
|
||||
const descriptor = {
|
||||
isDefaultEntry: existingDescriptor?.isDefaultEntry || policyId === undefined,
|
||||
specificTargetPolicies: addValueToSet(existingDescriptor?.specificTargetPolicies, policyId),
|
||||
entry: existingDescriptor?.entry || new ManifestEntry(artifact),
|
||||
};
|
||||
|
||||
this.allEntries.set(descriptor.entry.getDocId(), descriptor);
|
||||
|
||||
if (policyId) {
|
||||
const entries = this.policySpecificEntries.get(policyId) || new Map();
|
||||
entries.set(descriptor.entry.getDocId(), descriptor.entry);
|
||||
|
||||
this.policySpecificEntries.set(policyId, entries);
|
||||
} else {
|
||||
this.defaultEntries.set(descriptor.entry.getDocId(), descriptor.entry);
|
||||
}
|
||||
}
|
||||
|
||||
public contains(artifactId: string): boolean {
|
||||
return artifactId in this.entries;
|
||||
}
|
||||
|
||||
public getEntries(): Record<string, ManifestEntry> {
|
||||
return this.entries;
|
||||
}
|
||||
|
||||
public getEntry(artifactId: string): ManifestEntry | undefined {
|
||||
return this.entries[artifactId];
|
||||
public getAllArtifacts(): InternalArtifactSchema[] {
|
||||
return [...this.allEntries.values()].map((descriptor) => descriptor.entry.getArtifact());
|
||||
}
|
||||
|
||||
public getArtifact(artifactId: string): InternalArtifactSchema | undefined {
|
||||
return this.getEntry(artifactId)?.getArtifact();
|
||||
return this.allEntries.get(artifactId)?.entry.getArtifact();
|
||||
}
|
||||
|
||||
public diff(manifest: Manifest): ManifestDiff[] {
|
||||
const diffs: ManifestDiff[] = [];
|
||||
public containsArtifact(artifact: InternalArtifactSchema): boolean {
|
||||
return this.allEntries.has(getArtifactId(artifact));
|
||||
}
|
||||
|
||||
for (const id in manifest.getEntries()) {
|
||||
if (!this.contains(id)) {
|
||||
diffs.push({ type: 'delete', id });
|
||||
public isDefaultArtifact(artifact: InternalArtifactSchema): boolean | undefined {
|
||||
return this.allEntries.get(getArtifactId(artifact))?.isDefaultEntry;
|
||||
}
|
||||
|
||||
public getArtifactTargetPolicies(artifact: InternalArtifactSchema): Set<string> | undefined {
|
||||
return this.allEntries.get(getArtifactId(artifact))?.specificTargetPolicies;
|
||||
}
|
||||
|
||||
public diff(manifest: Manifest): ManifestDiff {
|
||||
const diff: ManifestDiff = {
|
||||
additions: [],
|
||||
removals: [],
|
||||
transitions: [],
|
||||
};
|
||||
|
||||
for (const artifact of manifest.getAllArtifacts()) {
|
||||
if (!this.containsArtifact(artifact)) {
|
||||
diff.removals.push(artifact);
|
||||
} else if (
|
||||
this.isDefaultArtifact(artifact) !== manifest.isDefaultArtifact(artifact) ||
|
||||
!isEqual(
|
||||
this.getArtifactTargetPolicies(artifact),
|
||||
manifest.getArtifactTargetPolicies(artifact)
|
||||
)
|
||||
) {
|
||||
diff.transitions.push(artifact);
|
||||
}
|
||||
}
|
||||
|
||||
for (const id in this.entries) {
|
||||
if (!manifest.contains(id)) {
|
||||
diffs.push({ type: 'add', id });
|
||||
for (const artifact of this.getAllArtifacts()) {
|
||||
if (!manifest.containsArtifact(artifact)) {
|
||||
diff.additions.push(artifact);
|
||||
}
|
||||
}
|
||||
|
||||
return diffs;
|
||||
return diff;
|
||||
}
|
||||
|
||||
public toEndpointFormat(): ManifestSchema {
|
||||
public toPackagePolicyManifest(policyId?: string): ManifestSchema {
|
||||
const entries = (!!policyId && this.policySpecificEntries.get(policyId)) || this.defaultEntries;
|
||||
const manifestObj: ManifestSchema = {
|
||||
manifest_version: this.getSemanticVersion(),
|
||||
schema_version: this.getSchemaVersion(),
|
||||
artifacts: {},
|
||||
};
|
||||
|
||||
for (const entry of Object.values(this.entries)) {
|
||||
for (const entry of entries.values()) {
|
||||
manifestObj.artifacts[entry.getIdentifier()] = entry.getRecord();
|
||||
}
|
||||
|
||||
|
@ -176,7 +191,15 @@ export class Manifest {
|
|||
|
||||
public toSavedObject(): InternalManifestSchema {
|
||||
return {
|
||||
ids: Object.keys(this.getEntries()),
|
||||
artifacts: [
|
||||
...createInternalManifestEntries([...this.defaultEntries.keys()]),
|
||||
...flatMap([...this.policySpecificEntries.keys()], (policyId) =>
|
||||
createInternalManifestEntries(
|
||||
[...(this.policySpecificEntries.get(policyId)?.keys() || [])],
|
||||
policyId
|
||||
)
|
||||
),
|
||||
],
|
||||
schemaVersion: this.getSchemaVersion(),
|
||||
semanticVersion: this.getSemanticVersion(),
|
||||
};
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 { SavedObjectUnsanitizedDoc } from 'kibana/server';
|
||||
import { migrationMocks } from 'src/core/server/mocks';
|
||||
import { ManifestConstants } from './common';
|
||||
import { migrations, OldInternalManifestSchema } from './migrations';
|
||||
|
||||
describe('7.12.0 manifest migrations', () => {
|
||||
const ARTIFACT_ID_0 =
|
||||
'endpoint-exceptionlist-macos-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3';
|
||||
const ARTIFACT_ID_1 =
|
||||
'endpoint-exceptionlist-windows-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3';
|
||||
const ARTIFACT_ID_2 =
|
||||
'endpoint-trustlist-macos-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3';
|
||||
const ARTIFACT_ID_3 =
|
||||
'endpoint-trustlist-windows-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3';
|
||||
|
||||
const migration = migrations['7.12.0'];
|
||||
|
||||
test('Migrates ids property', () => {
|
||||
const doc: SavedObjectUnsanitizedDoc<OldInternalManifestSchema> = {
|
||||
attributes: {
|
||||
ids: [ARTIFACT_ID_0, ARTIFACT_ID_1, ARTIFACT_ID_2, ARTIFACT_ID_3],
|
||||
schemaVersion: 'v1',
|
||||
semanticVersion: '1.0.1',
|
||||
},
|
||||
id: 'endpoint-manifest-v1',
|
||||
migrationVersion: {},
|
||||
references: [],
|
||||
type: ManifestConstants.SAVED_OBJECT_TYPE,
|
||||
updated_at: '2020-06-09T20:18:20.349Z',
|
||||
};
|
||||
|
||||
expect(migration(doc, migrationMocks.createContext())).toStrictEqual({
|
||||
attributes: {
|
||||
artifacts: [
|
||||
{ artifactId: ARTIFACT_ID_0, policyId: undefined },
|
||||
{ artifactId: ARTIFACT_ID_1, policyId: undefined },
|
||||
{ artifactId: ARTIFACT_ID_2, policyId: undefined },
|
||||
{ artifactId: ARTIFACT_ID_3, policyId: undefined },
|
||||
],
|
||||
schemaVersion: 'v1',
|
||||
semanticVersion: '1.0.1',
|
||||
},
|
||||
id: 'endpoint-manifest-v1',
|
||||
migrationVersion: {},
|
||||
references: [],
|
||||
type: ManifestConstants.SAVED_OBJECT_TYPE,
|
||||
updated_at: '2020-06-09T20:18:20.349Z',
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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 {
|
||||
SavedObjectMigrationMap,
|
||||
SavedObjectSanitizedDoc,
|
||||
SavedObjectUnsanitizedDoc,
|
||||
} from 'kibana/server';
|
||||
|
||||
import { InternalManifestSchema } from '../../schemas/artifacts';
|
||||
|
||||
export type OldInternalManifestSchema = Omit<InternalManifestSchema, 'artifacts'> & {
|
||||
ids: string[];
|
||||
};
|
||||
|
||||
export const migrations: SavedObjectMigrationMap = {
|
||||
'7.12.0': (
|
||||
doc: SavedObjectUnsanitizedDoc<OldInternalManifestSchema>
|
||||
): SavedObjectSanitizedDoc<InternalManifestSchema> => {
|
||||
const { ids, ...rest } = doc.attributes;
|
||||
|
||||
return {
|
||||
...doc,
|
||||
references: doc.references || [],
|
||||
attributes: {
|
||||
...rest,
|
||||
artifacts: (ids || []).map((artifactId) => ({ artifactId, policyId: undefined })),
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
|
@ -5,7 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { PackagePolicy } from '../../../../../fleet/common';
|
||||
import { mapValues } from 'lodash';
|
||||
import { PackagePolicy, PackagePolicyConfigRecord } from '../../../../../fleet/common';
|
||||
import { createPackagePolicyMock } from '../../../../../fleet/common/mocks';
|
||||
import { InternalArtifactCompleteSchema } from '../../schemas/artifacts';
|
||||
import {
|
||||
|
@ -63,83 +64,94 @@ export const getMockManifest = async (opts?: { compress: boolean }) => {
|
|||
return manifest;
|
||||
};
|
||||
|
||||
export const getMockManifestWithDiffs = async (opts?: { compress: boolean }) => {
|
||||
const manifest = new Manifest();
|
||||
const artifacts = await getMockArtifactsWithDiff(opts);
|
||||
artifacts.forEach((artifact) => manifest.addEntry(artifact));
|
||||
return manifest;
|
||||
};
|
||||
const toArtifactRecord = (artifactName: string, artifact: InternalArtifactCompleteSchema) => ({
|
||||
compression_algorithm: artifact.compressionAlgorithm,
|
||||
decoded_sha256: artifact.decodedSha256,
|
||||
decoded_size: artifact.decodedSize,
|
||||
encoded_sha256: artifact.encodedSha256,
|
||||
encoded_size: artifact.encodedSize,
|
||||
encryption_algorithm: artifact.encryptionAlgorithm,
|
||||
relative_url: `/api/endpoint/artifacts/download/${artifactName}/${artifact.decodedSha256}`,
|
||||
});
|
||||
|
||||
export const getEmptyMockManifest = async (opts?: { compress: boolean }) => {
|
||||
const manifest = new Manifest();
|
||||
const artifacts = await getEmptyMockArtifacts(opts);
|
||||
artifacts.forEach((artifact) => manifest.addEntry(artifact));
|
||||
return manifest;
|
||||
export const toArtifactRecords = (artifacts: Record<string, InternalArtifactCompleteSchema>) =>
|
||||
mapValues(artifacts, (artifact, key) => toArtifactRecord(key, artifact));
|
||||
|
||||
export const createPackagePolicyWithConfigMock = (
|
||||
options: Partial<PackagePolicy> & { config?: PackagePolicyConfigRecord }
|
||||
): PackagePolicy => {
|
||||
const { config, ...packagePolicyOverrides } = options;
|
||||
const packagePolicy = createPackagePolicyMock();
|
||||
packagePolicy.inputs[0].config = options.config;
|
||||
return { ...packagePolicy, ...packagePolicyOverrides };
|
||||
};
|
||||
|
||||
export const createPackagePolicyWithInitialManifestMock = (): PackagePolicy => {
|
||||
const packagePolicy = createPackagePolicyMock();
|
||||
packagePolicy.inputs[0].config!.artifact_manifest = {
|
||||
value: {
|
||||
artifacts: {
|
||||
'endpoint-exceptionlist-macos-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
encryption_algorithm: 'none',
|
||||
decoded_sha256: 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
encoded_sha256: 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
|
||||
decoded_size: 14,
|
||||
encoded_size: 22,
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-exceptionlist-macos-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
},
|
||||
'endpoint-exceptionlist-windows-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
encryption_algorithm: 'none',
|
||||
decoded_sha256: 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
encoded_sha256: 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
|
||||
decoded_size: 14,
|
||||
encoded_size: 22,
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-exceptionlist-windows-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
return createPackagePolicyWithConfigMock({
|
||||
config: {
|
||||
artifact_manifest: {
|
||||
value: {
|
||||
artifacts: {
|
||||
'endpoint-exceptionlist-macos-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
encryption_algorithm: 'none',
|
||||
decoded_sha256: 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
encoded_sha256: 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
|
||||
decoded_size: 14,
|
||||
encoded_size: 22,
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-exceptionlist-macos-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
},
|
||||
'endpoint-exceptionlist-windows-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
encryption_algorithm: 'none',
|
||||
decoded_sha256: 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
encoded_sha256: 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
|
||||
decoded_size: 14,
|
||||
encoded_size: 22,
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-exceptionlist-windows-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
|
||||
},
|
||||
},
|
||||
manifest_version: '1.0.0',
|
||||
schema_version: 'v1',
|
||||
},
|
||||
},
|
||||
manifest_version: '1.0.0',
|
||||
schema_version: 'v1',
|
||||
},
|
||||
};
|
||||
return packagePolicy;
|
||||
});
|
||||
};
|
||||
|
||||
export const createPackagePolicyWithManifestMock = (): PackagePolicy => {
|
||||
const packagePolicy = createPackagePolicyMock();
|
||||
packagePolicy.inputs[0].config!.artifact_manifest = {
|
||||
value: {
|
||||
artifacts: {
|
||||
'endpoint-exceptionlist-macos-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
encryption_algorithm: 'none',
|
||||
decoded_sha256: '96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
encoded_sha256: '975382ab55d019cbab0bbac207a54e2a7d489fad6e8f6de34fc6402e5ef37b1e',
|
||||
decoded_size: 432,
|
||||
encoded_size: 147,
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-exceptionlist-macos-v1/96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
},
|
||||
'endpoint-exceptionlist-windows-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
encryption_algorithm: 'none',
|
||||
decoded_sha256: '96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
encoded_sha256: '975382ab55d019cbab0bbac207a54e2a7d489fad6e8f6de34fc6402e5ef37b1e',
|
||||
decoded_size: 432,
|
||||
encoded_size: 147,
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-exceptionlist-windows-v1/96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
return createPackagePolicyWithConfigMock({
|
||||
config: {
|
||||
artifact_manifest: {
|
||||
value: {
|
||||
artifacts: {
|
||||
'endpoint-exceptionlist-macos-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
encryption_algorithm: 'none',
|
||||
decoded_sha256: '96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
encoded_sha256: '975382ab55d019cbab0bbac207a54e2a7d489fad6e8f6de34fc6402e5ef37b1e',
|
||||
decoded_size: 432,
|
||||
encoded_size: 147,
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-exceptionlist-macos-v1/96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
},
|
||||
'endpoint-exceptionlist-windows-v1': {
|
||||
compression_algorithm: 'zlib',
|
||||
encryption_algorithm: 'none',
|
||||
decoded_sha256: '96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
encoded_sha256: '975382ab55d019cbab0bbac207a54e2a7d489fad6e8f6de34fc6402e5ef37b1e',
|
||||
decoded_size: 432,
|
||||
encoded_size: 147,
|
||||
relative_url:
|
||||
'/api/endpoint/artifacts/download/endpoint-exceptionlist-windows-v1/96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
|
||||
},
|
||||
},
|
||||
manifest_version: '1.0.1',
|
||||
schema_version: 'v1',
|
||||
},
|
||||
},
|
||||
manifest_version: '1.0.1',
|
||||
schema_version: 'v1',
|
||||
},
|
||||
};
|
||||
|
||||
return packagePolicy;
|
||||
});
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import { SavedObjectsType } from '../../../../../../../src/core/server';
|
||||
|
||||
import { ArtifactConstants, ManifestConstants } from './common';
|
||||
import { migrations } from './migrations';
|
||||
|
||||
export const exceptionsArtifactSavedObjectType = ArtifactConstants.SAVED_OBJECT_TYPE;
|
||||
export const manifestSavedObjectType = ManifestConstants.SAVED_OBJECT_TYPE;
|
||||
|
@ -63,9 +64,18 @@ export const manifestSavedObjectMappings: SavedObjectsType['mappings'] = {
|
|||
type: 'keyword',
|
||||
index: false,
|
||||
},
|
||||
ids: {
|
||||
type: 'keyword',
|
||||
index: false,
|
||||
artifacts: {
|
||||
type: 'nested',
|
||||
properties: {
|
||||
policyId: {
|
||||
type: 'keyword',
|
||||
index: false,
|
||||
},
|
||||
artifactId: {
|
||||
type: 'keyword',
|
||||
index: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -82,4 +92,5 @@ export const manifestType: SavedObjectsType = {
|
|||
hidden: false,
|
||||
namespaceType: 'agnostic',
|
||||
mappings: manifestSavedObjectMappings,
|
||||
migrations,
|
||||
};
|
||||
|
|
|
@ -12,8 +12,27 @@ import { createMockEndpointAppContext } from '../../mocks';
|
|||
|
||||
import { ManifestTaskConstants, ManifestTask } from './task';
|
||||
import { MockManifestTask } from './task.mock';
|
||||
import { ManifestManager } from '../../services/artifacts/manifest_manager';
|
||||
import { buildManifestManagerMock } from '../../services/artifacts/manifest_manager/manifest_manager.mock';
|
||||
import { InternalArtifactCompleteSchema } from '../../schemas/artifacts';
|
||||
import { getMockArtifacts } from './mocks';
|
||||
import { Manifest } from './manifest';
|
||||
|
||||
describe('task', () => {
|
||||
const MOCK_TASK_INSTANCE = {
|
||||
id: `${ManifestTaskConstants.TYPE}:1.0.0`,
|
||||
runAt: new Date(),
|
||||
attempts: 0,
|
||||
ownerId: '',
|
||||
status: TaskStatus.Running,
|
||||
startedAt: new Date(),
|
||||
scheduledAt: new Date(),
|
||||
retryAt: new Date(),
|
||||
params: {},
|
||||
state: {},
|
||||
taskType: ManifestTaskConstants.TYPE,
|
||||
};
|
||||
|
||||
describe('Periodic task sanity checks', () => {
|
||||
test('can create task', () => {
|
||||
const manifestTask = new ManifestTask({
|
||||
|
@ -50,25 +69,255 @@ describe('task', () => {
|
|||
endpointAppContext: mockContext,
|
||||
taskManager: mockTaskManager,
|
||||
});
|
||||
const mockTaskInstance = {
|
||||
id: ManifestTaskConstants.TYPE,
|
||||
runAt: new Date(),
|
||||
attempts: 0,
|
||||
ownerId: '',
|
||||
status: TaskStatus.Running,
|
||||
startedAt: new Date(),
|
||||
scheduledAt: new Date(),
|
||||
retryAt: new Date(),
|
||||
params: {},
|
||||
state: {},
|
||||
taskType: ManifestTaskConstants.TYPE,
|
||||
};
|
||||
const createTaskRunner =
|
||||
mockTaskManager.registerTaskDefinitions.mock.calls[0][0][ManifestTaskConstants.TYPE]
|
||||
.createTaskRunner;
|
||||
const taskRunner = createTaskRunner({ taskInstance: mockTaskInstance });
|
||||
const taskRunner = createTaskRunner({ taskInstance: MOCK_TASK_INSTANCE });
|
||||
await taskRunner.run();
|
||||
expect(mockManifestTask.runTask).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Artifacts generation flow tests', () => {
|
||||
const runTask = async (manifestManager: ManifestManager) => {
|
||||
const mockContext = createMockEndpointAppContext();
|
||||
const mockTaskManager = taskManagerMock.createSetup();
|
||||
|
||||
new ManifestTask({
|
||||
endpointAppContext: mockContext,
|
||||
taskManager: mockTaskManager,
|
||||
});
|
||||
|
||||
mockContext.service.getManifestManager = jest.fn().mockReturnValue(manifestManager);
|
||||
|
||||
const createTaskRunner =
|
||||
mockTaskManager.registerTaskDefinitions.mock.calls[0][0][ManifestTaskConstants.TYPE]
|
||||
.createTaskRunner;
|
||||
const taskRunner = createTaskRunner({ taskInstance: MOCK_TASK_INSTANCE });
|
||||
await taskRunner.run();
|
||||
};
|
||||
|
||||
const TEST_POLICY_ID_1 = 'c6d16e42-c32d-4dce-8a88-113cfe276ad1';
|
||||
const TEST_POLICY_ID_2 = '93c46720-c217-11ea-9906-b5b8a21b268e';
|
||||
const ARTIFACT_ID_1 =
|
||||
'endpoint-exceptionlist-windows-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3';
|
||||
let ARTIFACT_EXCEPTIONS_MACOS: InternalArtifactCompleteSchema;
|
||||
let ARTIFACT_EXCEPTIONS_WINDOWS: InternalArtifactCompleteSchema;
|
||||
let ARTIFACT_TRUSTED_APPS_MACOS: InternalArtifactCompleteSchema;
|
||||
|
||||
beforeAll(async () => {
|
||||
const artifacts = await getMockArtifacts({ compress: true });
|
||||
ARTIFACT_EXCEPTIONS_MACOS = artifacts[0];
|
||||
ARTIFACT_EXCEPTIONS_WINDOWS = artifacts[1];
|
||||
ARTIFACT_TRUSTED_APPS_MACOS = artifacts[2];
|
||||
});
|
||||
|
||||
test('Should not run the process when no current manifest manager', async () => {
|
||||
const manifestManager = buildManifestManagerMock();
|
||||
|
||||
manifestManager.getLastComputedManifest = jest.fn().mockReturnValue(null);
|
||||
|
||||
await runTask(manifestManager);
|
||||
|
||||
expect(manifestManager.getLastComputedManifest).toHaveBeenCalled();
|
||||
expect(manifestManager.buildNewManifest).not.toHaveBeenCalled();
|
||||
expect(manifestManager.pushArtifacts).not.toHaveBeenCalled();
|
||||
expect(manifestManager.commit).not.toHaveBeenCalled();
|
||||
expect(manifestManager.tryDispatch).not.toHaveBeenCalled();
|
||||
expect(manifestManager.deleteArtifacts).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('Should stop the process when no building new manifest throws error', async () => {
|
||||
const manifestManager = buildManifestManagerMock();
|
||||
const lastManifest = Manifest.getDefault();
|
||||
|
||||
manifestManager.getLastComputedManifest = jest.fn().mockReturnValue(lastManifest);
|
||||
manifestManager.buildNewManifest = jest.fn().mockRejectedValue(new Error());
|
||||
|
||||
await runTask(manifestManager);
|
||||
|
||||
expect(manifestManager.getLastComputedManifest).toHaveBeenCalled();
|
||||
expect(manifestManager.buildNewManifest).toHaveBeenCalledWith(lastManifest);
|
||||
expect(manifestManager.pushArtifacts).not.toHaveBeenCalled();
|
||||
expect(manifestManager.commit).not.toHaveBeenCalled();
|
||||
expect(manifestManager.tryDispatch).not.toHaveBeenCalled();
|
||||
expect(manifestManager.deleteArtifacts).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('Should not bump version and commit manifest when no diff in the manifest', async () => {
|
||||
const manifestManager = buildManifestManagerMock();
|
||||
|
||||
const lastManifest = Manifest.getDefault();
|
||||
lastManifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
lastManifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS);
|
||||
|
||||
const newManifest = Manifest.getDefault();
|
||||
newManifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
newManifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS);
|
||||
|
||||
manifestManager.getLastComputedManifest = jest.fn().mockReturnValue(lastManifest);
|
||||
manifestManager.buildNewManifest = jest.fn().mockResolvedValue(newManifest);
|
||||
manifestManager.pushArtifacts = jest.fn().mockResolvedValue([]);
|
||||
manifestManager.tryDispatch = jest.fn().mockResolvedValue([]);
|
||||
manifestManager.deleteArtifacts = jest.fn().mockResolvedValue([]);
|
||||
|
||||
await runTask(manifestManager);
|
||||
|
||||
expect(newManifest.getSemanticVersion()).toBe('1.0.0');
|
||||
|
||||
expect(manifestManager.getLastComputedManifest).toHaveBeenCalled();
|
||||
expect(manifestManager.buildNewManifest).toHaveBeenCalledWith(lastManifest);
|
||||
expect(manifestManager.pushArtifacts).toHaveBeenCalledWith([]);
|
||||
expect(manifestManager.commit).not.toHaveBeenCalled();
|
||||
expect(manifestManager.tryDispatch).toHaveBeenCalledWith(newManifest);
|
||||
expect(manifestManager.deleteArtifacts).toHaveBeenCalledWith([]);
|
||||
});
|
||||
|
||||
test('Should stop the process when there are errors pushing new artifacts', async () => {
|
||||
const manifestManager = buildManifestManagerMock();
|
||||
|
||||
const lastManifest = Manifest.getDefault();
|
||||
|
||||
const newManifest = Manifest.getDefault();
|
||||
newManifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
newManifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS);
|
||||
|
||||
manifestManager.getLastComputedManifest = jest.fn().mockReturnValue(lastManifest);
|
||||
manifestManager.buildNewManifest = jest.fn().mockResolvedValue(newManifest);
|
||||
manifestManager.pushArtifacts = jest.fn().mockResolvedValue([new Error()]);
|
||||
|
||||
await runTask(manifestManager);
|
||||
|
||||
expect(newManifest.getSemanticVersion()).toBe('1.0.0');
|
||||
|
||||
expect(manifestManager.getLastComputedManifest).toHaveBeenCalled();
|
||||
expect(manifestManager.buildNewManifest).toHaveBeenCalledWith(lastManifest);
|
||||
expect(manifestManager.pushArtifacts).toHaveBeenCalledWith([
|
||||
ARTIFACT_EXCEPTIONS_MACOS,
|
||||
ARTIFACT_TRUSTED_APPS_MACOS,
|
||||
]);
|
||||
expect(manifestManager.commit).not.toHaveBeenCalled();
|
||||
expect(manifestManager.tryDispatch).not.toHaveBeenCalled();
|
||||
expect(manifestManager.deleteArtifacts).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('Should stop the process when there are errors committing manifest', async () => {
|
||||
const manifestManager = buildManifestManagerMock();
|
||||
|
||||
const lastManifest = Manifest.getDefault();
|
||||
|
||||
const newManifest = Manifest.getDefault();
|
||||
newManifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
newManifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS);
|
||||
|
||||
manifestManager.getLastComputedManifest = jest.fn().mockReturnValue(lastManifest);
|
||||
manifestManager.buildNewManifest = jest.fn().mockResolvedValue(newManifest);
|
||||
manifestManager.pushArtifacts = jest.fn().mockResolvedValue([]);
|
||||
manifestManager.commit = jest.fn().mockRejectedValue(new Error());
|
||||
|
||||
await runTask(manifestManager);
|
||||
|
||||
expect(newManifest.getSemanticVersion()).toBe('1.0.1');
|
||||
|
||||
expect(manifestManager.getLastComputedManifest).toHaveBeenCalled();
|
||||
expect(manifestManager.buildNewManifest).toHaveBeenCalledWith(lastManifest);
|
||||
expect(manifestManager.pushArtifacts).toHaveBeenCalledWith([
|
||||
ARTIFACT_EXCEPTIONS_MACOS,
|
||||
ARTIFACT_TRUSTED_APPS_MACOS,
|
||||
]);
|
||||
expect(manifestManager.commit).toHaveBeenCalledWith(newManifest);
|
||||
expect(manifestManager.tryDispatch).not.toHaveBeenCalled();
|
||||
expect(manifestManager.deleteArtifacts).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('Should stop the process when there are errors dispatching manifest', async () => {
|
||||
const manifestManager = buildManifestManagerMock();
|
||||
|
||||
const lastManifest = Manifest.getDefault();
|
||||
|
||||
const newManifest = Manifest.getDefault();
|
||||
newManifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
newManifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS);
|
||||
|
||||
manifestManager.getLastComputedManifest = jest.fn().mockReturnValue(lastManifest);
|
||||
manifestManager.buildNewManifest = jest.fn().mockResolvedValue(newManifest);
|
||||
manifestManager.pushArtifacts = jest.fn().mockResolvedValue([]);
|
||||
manifestManager.commit = jest.fn().mockResolvedValue(null);
|
||||
manifestManager.tryDispatch = jest.fn().mockResolvedValue([new Error()]);
|
||||
|
||||
await runTask(manifestManager);
|
||||
|
||||
expect(newManifest.getSemanticVersion()).toBe('1.0.1');
|
||||
|
||||
expect(manifestManager.getLastComputedManifest).toHaveBeenCalled();
|
||||
expect(manifestManager.buildNewManifest).toHaveBeenCalledWith(lastManifest);
|
||||
expect(manifestManager.pushArtifacts).toHaveBeenCalledWith([
|
||||
ARTIFACT_EXCEPTIONS_MACOS,
|
||||
ARTIFACT_TRUSTED_APPS_MACOS,
|
||||
]);
|
||||
expect(manifestManager.commit).toHaveBeenCalledWith(newManifest);
|
||||
expect(manifestManager.tryDispatch).toHaveBeenCalledWith(newManifest);
|
||||
expect(manifestManager.deleteArtifacts).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('Should succeed the process and delete old artifacts', async () => {
|
||||
const manifestManager = buildManifestManagerMock();
|
||||
|
||||
const lastManifest = Manifest.getDefault();
|
||||
lastManifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
lastManifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS);
|
||||
|
||||
const newManifest = Manifest.getDefault();
|
||||
newManifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
newManifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS);
|
||||
|
||||
manifestManager.getLastComputedManifest = jest.fn().mockReturnValue(lastManifest);
|
||||
manifestManager.buildNewManifest = jest.fn().mockResolvedValue(newManifest);
|
||||
manifestManager.pushArtifacts = jest.fn().mockResolvedValue([]);
|
||||
manifestManager.commit = jest.fn().mockResolvedValue(null);
|
||||
manifestManager.tryDispatch = jest.fn().mockResolvedValue([]);
|
||||
manifestManager.deleteArtifacts = jest.fn().mockResolvedValue([]);
|
||||
|
||||
await runTask(manifestManager);
|
||||
|
||||
expect(newManifest.getSemanticVersion()).toBe('1.0.1');
|
||||
|
||||
expect(manifestManager.getLastComputedManifest).toHaveBeenCalled();
|
||||
expect(manifestManager.buildNewManifest).toHaveBeenCalledWith(lastManifest);
|
||||
expect(manifestManager.pushArtifacts).toHaveBeenCalledWith([ARTIFACT_TRUSTED_APPS_MACOS]);
|
||||
expect(manifestManager.commit).toHaveBeenCalledWith(newManifest);
|
||||
expect(manifestManager.tryDispatch).toHaveBeenCalledWith(newManifest);
|
||||
expect(manifestManager.deleteArtifacts).toHaveBeenCalledWith([ARTIFACT_ID_1]);
|
||||
});
|
||||
|
||||
test('Should succeed the process but not add or delete artifacts when there are only transitions', async () => {
|
||||
const manifestManager = buildManifestManagerMock();
|
||||
|
||||
const lastManifest = Manifest.getDefault();
|
||||
lastManifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS);
|
||||
lastManifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_1);
|
||||
|
||||
const newManifest = Manifest.getDefault();
|
||||
newManifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1);
|
||||
newManifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_2);
|
||||
|
||||
manifestManager.getLastComputedManifest = jest.fn().mockReturnValue(lastManifest);
|
||||
manifestManager.buildNewManifest = jest.fn().mockResolvedValue(newManifest);
|
||||
manifestManager.pushArtifacts = jest.fn().mockResolvedValue([]);
|
||||
manifestManager.commit = jest.fn().mockResolvedValue(null);
|
||||
manifestManager.tryDispatch = jest.fn().mockResolvedValue([]);
|
||||
manifestManager.deleteArtifacts = jest.fn().mockResolvedValue([]);
|
||||
|
||||
await runTask(manifestManager);
|
||||
|
||||
expect(newManifest.getSemanticVersion()).toBe('1.0.1');
|
||||
|
||||
expect(manifestManager.getLastComputedManifest).toHaveBeenCalled();
|
||||
expect(manifestManager.buildNewManifest).toHaveBeenCalledWith(lastManifest);
|
||||
expect(manifestManager.pushArtifacts).toHaveBeenCalledWith([]);
|
||||
expect(manifestManager.commit).toHaveBeenCalledWith(newManifest);
|
||||
expect(manifestManager.tryDispatch).toHaveBeenCalledWith(newManifest);
|
||||
expect(manifestManager.deleteArtifacts).toHaveBeenCalledWith([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -12,8 +12,9 @@ import {
|
|||
TaskManagerStartContract,
|
||||
} from '../../../../../task_manager/server';
|
||||
import { EndpointAppContext } from '../../types';
|
||||
import { reportErrors } from './common';
|
||||
import { getArtifactId, reportErrors } from './common';
|
||||
import { InternalArtifactCompleteSchema } from '../../schemas/artifacts';
|
||||
import { isEmptyManifestDiff } from './manifest';
|
||||
|
||||
export const ManifestTaskConstants = {
|
||||
TIMEOUT: '1m',
|
||||
|
@ -114,39 +115,23 @@ export class ManifestTask {
|
|||
return;
|
||||
}
|
||||
|
||||
// New computed manifest based on current state of exception list
|
||||
// New computed manifest based on current manifest
|
||||
const newManifest = await manifestManager.buildNewManifest(oldManifest);
|
||||
const diffs = newManifest.diff(oldManifest);
|
||||
|
||||
// Compress new artifacts
|
||||
const adds = diffs.filter((diff) => diff.type === 'add').map((diff) => diff.id);
|
||||
for (const artifactId of adds) {
|
||||
const compressError = await newManifest.compressArtifact(artifactId);
|
||||
if (compressError) {
|
||||
throw compressError;
|
||||
}
|
||||
}
|
||||
const diff = newManifest.diff(oldManifest);
|
||||
|
||||
// Persist new artifacts
|
||||
const artifacts = adds
|
||||
.map((artifactId) => newManifest.getArtifact(artifactId))
|
||||
.filter((artifact): artifact is InternalArtifactCompleteSchema => artifact !== undefined);
|
||||
if (artifacts.length !== adds.length) {
|
||||
throw new Error('Invalid artifact encountered.');
|
||||
}
|
||||
const persistErrors = await manifestManager.pushArtifacts(artifacts);
|
||||
const persistErrors = await manifestManager.pushArtifacts(
|
||||
diff.additions as InternalArtifactCompleteSchema[]
|
||||
);
|
||||
if (persistErrors.length) {
|
||||
reportErrors(this.logger, persistErrors);
|
||||
throw new Error('Unable to persist new artifacts.');
|
||||
}
|
||||
|
||||
// Commit latest manifest state, if different
|
||||
if (diffs.length) {
|
||||
if (!isEmptyManifestDiff(diff)) {
|
||||
// Commit latest manifest state
|
||||
newManifest.bumpSemanticVersion();
|
||||
const error = await manifestManager.commit(newManifest);
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
await manifestManager.commit(newManifest);
|
||||
}
|
||||
|
||||
// Try dispatching to ingest-manager package policies
|
||||
|
@ -157,8 +142,9 @@ export class ManifestTask {
|
|||
}
|
||||
|
||||
// Try to clean up superceded artifacts
|
||||
const deletes = diffs.filter((diff) => diff.type === 'delete').map((diff) => diff.id);
|
||||
const deleteErrors = await manifestManager.deleteArtifacts(deletes);
|
||||
const deleteErrors = await manifestManager.deleteArtifacts(
|
||||
diff.removals.map((artifact) => getArtifactId(artifact))
|
||||
);
|
||||
if (deleteErrors.length) {
|
||||
reportErrors(this.logger, deleteErrors);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ import {
|
|||
loggingSystemMock,
|
||||
} from 'src/core/server/mocks';
|
||||
import { ArtifactConstants } from '../../lib/artifacts';
|
||||
import { registerDownloadExceptionListRoute } from './download_exception_list';
|
||||
import { registerDownloadArtifactRoute } from './download_artifact';
|
||||
import { EndpointAppContextService } from '../../endpoint_app_context_services';
|
||||
import { createMockEndpointAppContextServiceStartContract } from '../../mocks';
|
||||
import { createMockConfig } from '../../../lib/detection_engine/routes/__mocks__';
|
||||
|
@ -121,7 +121,7 @@ describe('test alerts route', () => {
|
|||
);
|
||||
endpointAppContextService.start(startContract);
|
||||
|
||||
registerDownloadExceptionListRoute(
|
||||
registerDownloadArtifactRoute(
|
||||
routerMock,
|
||||
{
|
||||
logFactory: loggingSystemMock.create(),
|
|
@ -29,9 +29,9 @@ import { EndpointAppContext } from '../../types';
|
|||
const allowlistBaseRoute: string = '/api/endpoint/artifacts';
|
||||
|
||||
/**
|
||||
* Registers the exception list route to enable sensors to download an allowlist artifact
|
||||
* Registers the artifact download route to enable sensors to download an allowlist artifact
|
||||
*/
|
||||
export function registerDownloadExceptionListRoute(
|
||||
export function registerDownloadArtifactRoute(
|
||||
router: IRouter,
|
||||
endpointContext: EndpointAppContext,
|
||||
cache: LRU<string, Buffer>
|
||||
|
@ -49,7 +49,7 @@ export function registerDownloadExceptionListRoute(
|
|||
},
|
||||
async (context, req, res) => {
|
||||
let scopedSOClient: SavedObjectsClientContract;
|
||||
const logger = endpointContext.logFactory.get('download_exception_list');
|
||||
const logger = endpointContext.logFactory.get('download_artifact');
|
||||
|
||||
// The ApiKey must be associated with an enrolled Fleet agent
|
||||
try {
|
|
@ -5,4 +5,4 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export * from './download_exception_list';
|
||||
export * from './download_artifact';
|
||||
|
|
|
@ -46,14 +46,10 @@ export const getInternalArtifactMock = async (
|
|||
export const getEmptyInternalArtifactMock = async (
|
||||
os: string,
|
||||
schemaVersion: string,
|
||||
opts?: { compress: boolean }
|
||||
opts?: { compress: boolean },
|
||||
artifactName: string = ArtifactConstants.GLOBAL_ALLOWLIST_NAME
|
||||
): Promise<InternalArtifactCompleteSchema> => {
|
||||
const artifact = await buildArtifact(
|
||||
{ entries: [] },
|
||||
os,
|
||||
schemaVersion,
|
||||
ArtifactConstants.GLOBAL_ALLOWLIST_NAME
|
||||
);
|
||||
const artifact = await buildArtifact({ entries: [] }, os, schemaVersion, artifactName);
|
||||
return opts?.compress ? compressArtifact(artifact) : artifact;
|
||||
};
|
||||
|
||||
|
@ -74,7 +70,7 @@ export const getInternalArtifactMockWithDiffs = async (
|
|||
};
|
||||
|
||||
export const getInternalManifestMock = (): InternalManifestSchema => ({
|
||||
ids: [],
|
||||
artifacts: [],
|
||||
schemaVersion: 'v1',
|
||||
semanticVersion: '1.0.0',
|
||||
});
|
||||
|
|
|
@ -58,9 +58,17 @@ export const internalArtifactCreateSchema = t.intersection([
|
|||
]);
|
||||
export type InternalArtifactCreateSchema = t.TypeOf<typeof internalArtifactCreateSchema>;
|
||||
|
||||
export const internalManifestEntrySchema = t.exact(
|
||||
t.type({
|
||||
policyId: t.union([identifier, t.undefined]),
|
||||
artifactId: identifier,
|
||||
})
|
||||
);
|
||||
export type InternalManifestEntrySchema = t.TypeOf<typeof internalManifestEntrySchema>;
|
||||
|
||||
export const internalManifestSchema = t.exact(
|
||||
t.type({
|
||||
ids: t.array(identifier),
|
||||
artifacts: t.array(internalManifestEntrySchema),
|
||||
schemaVersion: manifestSchemaVersion,
|
||||
semanticVersion,
|
||||
})
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* 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 { savedObjectsClientMock } from 'src/core/server/mocks';
|
||||
import { SavedObjectsClientContract } from 'src/core/server';
|
||||
import { ArtifactClient } from './artifact_client';
|
||||
|
||||
export const getArtifactClientMock = (
|
||||
savedObjectsClient?: SavedObjectsClientContract
|
||||
): ArtifactClient => {
|
||||
if (savedObjectsClient !== undefined) {
|
||||
return new ArtifactClient(savedObjectsClient);
|
||||
}
|
||||
return new ArtifactClient(savedObjectsClientMock.create());
|
||||
};
|
|
@ -8,7 +8,6 @@
|
|||
import { savedObjectsClientMock } from 'src/core/server/mocks';
|
||||
import { ArtifactConstants, getArtifactId } from '../../lib/artifacts';
|
||||
import { getInternalArtifactMock } from '../../schemas/artifacts/saved_objects.mock';
|
||||
import { getArtifactClientMock } from './artifact_client.mock';
|
||||
import { ArtifactClient } from './artifact_client';
|
||||
|
||||
describe('artifact_client', () => {
|
||||
|
@ -20,14 +19,14 @@ describe('artifact_client', () => {
|
|||
|
||||
test('can get artifact', async () => {
|
||||
const savedObjectsClient = savedObjectsClientMock.create();
|
||||
const artifactClient = getArtifactClientMock(savedObjectsClient);
|
||||
const artifactClient = new ArtifactClient(savedObjectsClient);
|
||||
await artifactClient.getArtifact('abcd');
|
||||
expect(savedObjectsClient.get).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('can create artifact', async () => {
|
||||
const savedObjectsClient = savedObjectsClientMock.create();
|
||||
const artifactClient = getArtifactClientMock(savedObjectsClient);
|
||||
const artifactClient = new ArtifactClient(savedObjectsClient);
|
||||
const artifact = await getInternalArtifactMock('linux', 'v1');
|
||||
await artifactClient.createArtifact(artifact);
|
||||
expect(savedObjectsClient.create).toHaveBeenCalledWith(
|
||||
|
@ -42,7 +41,7 @@ describe('artifact_client', () => {
|
|||
|
||||
test('can delete artifact', async () => {
|
||||
const savedObjectsClient = savedObjectsClientMock.create();
|
||||
const artifactClient = getArtifactClientMock(savedObjectsClient);
|
||||
const artifactClient = new ArtifactClient(savedObjectsClient);
|
||||
await artifactClient.deleteArtifact('abcd');
|
||||
expect(savedObjectsClient.delete).toHaveBeenCalledWith(
|
||||
ArtifactConstants.SAVED_OBJECT_TYPE,
|
||||
|
|
|
@ -5,16 +5,14 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import LRU from 'lru-cache';
|
||||
import { savedObjectsClientMock, loggingSystemMock } from 'src/core/server/mocks';
|
||||
import { Logger } from 'src/core/server';
|
||||
import { PackagePolicyServiceInterface } from '../../../../../../fleet/server';
|
||||
import { createPackagePolicyServiceMock } from '../../../../../../fleet/server/mocks';
|
||||
import { ExceptionListClient } from '../../../../../../lists/server';
|
||||
import { listMock } from '../../../../../../lists/server/mocks';
|
||||
import LRU from 'lru-cache';
|
||||
import { getArtifactClientMock } from '../artifact_client.mock';
|
||||
import { getManifestClientMock } from '../manifest_client.mock';
|
||||
import { ManifestManager } from './manifest_manager';
|
||||
import { ExceptionListItemSchema } from '../../../../../../lists/common/schemas/response';
|
||||
import {
|
||||
createPackagePolicyWithManifestMock,
|
||||
createPackagePolicyWithInitialManifestMock,
|
||||
|
@ -22,6 +20,32 @@ import {
|
|||
getMockArtifactsWithDiff,
|
||||
getEmptyMockArtifacts,
|
||||
} from '../../../lib/artifacts/mocks';
|
||||
import { ArtifactClient } from '../artifact_client';
|
||||
import { getManifestClientMock } from '../manifest_client.mock';
|
||||
import { ManifestManager, ManifestManagerContext } from './manifest_manager';
|
||||
|
||||
export const createExceptionListResponse = (data: ExceptionListItemSchema[], total?: number) => ({
|
||||
data,
|
||||
page: 1,
|
||||
per_page: 100,
|
||||
total: total || data.length,
|
||||
});
|
||||
|
||||
type FindExceptionListItemOptions = Parameters<ExceptionListClient['findExceptionListItem']>[0];
|
||||
|
||||
const FILTER_REGEXP = /^exception-list-agnostic\.attributes\.os_types:"(\w+)"$/;
|
||||
|
||||
export const mockFindExceptionListItemResponses = (
|
||||
responses: Record<string, Record<string, ExceptionListItemSchema[]>>
|
||||
) => {
|
||||
return jest.fn().mockImplementation((options: FindExceptionListItemOptions) => {
|
||||
const os = FILTER_REGEXP.test(options.filter || '')
|
||||
? options.filter!.match(FILTER_REGEXP)![1]
|
||||
: '';
|
||||
|
||||
return createExceptionListResponse(responses[options.listId]?.[os] || []);
|
||||
});
|
||||
};
|
||||
|
||||
export enum ManifestManagerMockType {
|
||||
InitialSystemState,
|
||||
|
@ -29,28 +53,54 @@ export enum ManifestManagerMockType {
|
|||
NormalFlow,
|
||||
}
|
||||
|
||||
export const getManifestManagerMock = (opts?: {
|
||||
mockType?: ManifestManagerMockType;
|
||||
cache?: LRU<string, Buffer>;
|
||||
exceptionListClient?: ExceptionListClient;
|
||||
packagePolicyService?: jest.Mocked<PackagePolicyServiceInterface>;
|
||||
savedObjectsClient?: ReturnType<typeof savedObjectsClientMock.create>;
|
||||
}): ManifestManager => {
|
||||
let cache = new LRU<string, Buffer>({ max: 10, maxAge: 1000 * 60 * 60 });
|
||||
if (opts?.cache != null) {
|
||||
cache = opts.cache;
|
||||
}
|
||||
export interface ManifestManagerMockOptions {
|
||||
cache: LRU<string, Buffer>;
|
||||
exceptionListClient: ExceptionListClient;
|
||||
packagePolicyService: jest.Mocked<PackagePolicyServiceInterface>;
|
||||
savedObjectsClient: ReturnType<typeof savedObjectsClientMock.create>;
|
||||
}
|
||||
|
||||
let exceptionListClient = listMock.getExceptionListClient();
|
||||
if (opts?.exceptionListClient != null) {
|
||||
exceptionListClient = opts.exceptionListClient;
|
||||
}
|
||||
export const buildManifestManagerMockOptions = (
|
||||
opts: Partial<ManifestManagerMockOptions>
|
||||
): ManifestManagerMockOptions => ({
|
||||
cache: new LRU<string, Buffer>({ max: 10, maxAge: 1000 * 60 * 60 }),
|
||||
exceptionListClient: listMock.getExceptionListClient(),
|
||||
packagePolicyService: createPackagePolicyServiceMock(),
|
||||
savedObjectsClient: savedObjectsClientMock.create(),
|
||||
...opts,
|
||||
});
|
||||
|
||||
let packagePolicyService = createPackagePolicyServiceMock();
|
||||
if (opts?.packagePolicyService != null) {
|
||||
packagePolicyService = opts.packagePolicyService;
|
||||
}
|
||||
packagePolicyService.list = jest.fn().mockResolvedValue({
|
||||
export const buildManifestManagerContextMock = (
|
||||
opts: Partial<ManifestManagerMockOptions>
|
||||
): ManifestManagerContext => {
|
||||
const fullOpts = buildManifestManagerMockOptions(opts);
|
||||
|
||||
return {
|
||||
...fullOpts,
|
||||
artifactClient: new ArtifactClient(fullOpts.savedObjectsClient),
|
||||
logger: loggingSystemMock.create().get() as jest.Mocked<Logger>,
|
||||
};
|
||||
};
|
||||
|
||||
export const buildManifestManagerMock = (opts?: Partial<ManifestManagerMockOptions>) => {
|
||||
const manifestManager = new ManifestManager(buildManifestManagerContextMock(opts || {}));
|
||||
manifestManager.getLastComputedManifest = jest.fn();
|
||||
manifestManager.buildNewManifest = jest.fn();
|
||||
manifestManager.pushArtifacts = jest.fn();
|
||||
manifestManager.deleteArtifacts = jest.fn();
|
||||
manifestManager.commit = jest.fn();
|
||||
manifestManager.tryDispatch = jest.fn();
|
||||
|
||||
return manifestManager;
|
||||
};
|
||||
|
||||
export const getManifestManagerMock = (
|
||||
opts?: Partial<ManifestManagerMockOptions> & { mockType?: ManifestManagerMockType }
|
||||
): ManifestManager => {
|
||||
const { mockType = ManifestManagerMockType.NormalFlow, ...restOptions } = opts || {};
|
||||
const context = buildManifestManagerContextMock(restOptions);
|
||||
|
||||
context.packagePolicyService.list = jest.fn().mockResolvedValue({
|
||||
total: 1,
|
||||
items: [
|
||||
{ version: 'policy-1-version', ...createPackagePolicyWithManifestMock() },
|
||||
|
@ -59,19 +109,13 @@ export const getManifestManagerMock = (opts?: {
|
|||
],
|
||||
});
|
||||
|
||||
let savedObjectsClient = savedObjectsClientMock.create();
|
||||
if (opts?.savedObjectsClient != null) {
|
||||
savedObjectsClient = opts.savedObjectsClient;
|
||||
}
|
||||
|
||||
class ManifestManagerMock extends ManifestManager {
|
||||
protected buildExceptionListArtifacts = jest.fn().mockImplementation(() => {
|
||||
const mockType = opts?.mockType ?? ManifestManagerMockType.NormalFlow;
|
||||
switch (mockType) {
|
||||
case ManifestManagerMockType.InitialSystemState:
|
||||
return getEmptyMockArtifacts();
|
||||
case ManifestManagerMockType.ListClientPromiseRejection:
|
||||
exceptionListClient.findExceptionListItem = jest
|
||||
context.exceptionListClient.findExceptionListItem = jest
|
||||
.fn()
|
||||
.mockRejectedValue(new Error('unexpected thing happened'));
|
||||
return super.buildExceptionListArtifacts('v1');
|
||||
|
@ -81,7 +125,6 @@ export const getManifestManagerMock = (opts?: {
|
|||
});
|
||||
|
||||
public getLastComputedManifest = jest.fn().mockImplementation(() => {
|
||||
const mockType = opts?.mockType ?? ManifestManagerMockType.NormalFlow;
|
||||
switch (mockType) {
|
||||
case ManifestManagerMockType.InitialSystemState:
|
||||
return null;
|
||||
|
@ -95,14 +138,5 @@ export const getManifestManagerMock = (opts?: {
|
|||
.mockReturnValue(getManifestClientMock(this.savedObjectsClient));
|
||||
}
|
||||
|
||||
const manifestManager = new ManifestManagerMock({
|
||||
artifactClient: getArtifactClientMock(savedObjectsClient),
|
||||
cache,
|
||||
packagePolicyService,
|
||||
exceptionListClient,
|
||||
logger: loggingSystemMock.create().get() as jest.Mocked<Logger>,
|
||||
savedObjectsClient,
|
||||
});
|
||||
|
||||
return manifestManager;
|
||||
return new ManifestManagerMock(context);
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -6,20 +6,25 @@
|
|||
*/
|
||||
|
||||
import semver from 'semver';
|
||||
import { Logger, SavedObjectsClientContract } from 'src/core/server';
|
||||
import LRU from 'lru-cache';
|
||||
import { isEqual } from 'lodash';
|
||||
import { Logger, SavedObjectsClientContract } from 'src/core/server';
|
||||
import { PackagePolicyServiceInterface } from '../../../../../../fleet/server';
|
||||
import { ExceptionListClient } from '../../../../../../lists/server';
|
||||
import { ManifestSchemaVersion } from '../../../../../common/endpoint/schema/common';
|
||||
import { manifestDispatchSchema } from '../../../../../common/endpoint/schema/manifest';
|
||||
import {
|
||||
manifestDispatchSchema,
|
||||
ManifestSchema,
|
||||
} from '../../../../../common/endpoint/schema/manifest';
|
||||
|
||||
import {
|
||||
ArtifactConstants,
|
||||
buildArtifact,
|
||||
getArtifactId,
|
||||
getFullEndpointExceptionList,
|
||||
isCompressed,
|
||||
Manifest,
|
||||
ManifestDiff,
|
||||
maybeCompressArtifact,
|
||||
} from '../../../lib/artifacts';
|
||||
import {
|
||||
InternalArtifactCompleteSchema,
|
||||
|
@ -29,6 +34,7 @@ import { ArtifactClient } from '../artifact_client';
|
|||
import { ManifestClient } from '../manifest_client';
|
||||
import { ENDPOINT_LIST_ID } from '../../../../../../lists/common';
|
||||
import { ENDPOINT_TRUSTED_APPS_LIST_ID } from '../../../../../../lists/common/constants';
|
||||
import { PackagePolicy } from '../../../../../../fleet/common/types/models';
|
||||
|
||||
export interface ManifestManagerContext {
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
|
@ -39,14 +45,13 @@ export interface ManifestManagerContext {
|
|||
cache: LRU<string, Buffer>;
|
||||
}
|
||||
|
||||
export interface ManifestSnapshotOpts {
|
||||
initialize?: boolean;
|
||||
}
|
||||
const getArtifactIds = (manifest: ManifestSchema) =>
|
||||
[...Object.keys(manifest.artifacts)].map(
|
||||
(key) => `${key}-${manifest.artifacts[key].decoded_sha256}`
|
||||
);
|
||||
|
||||
export interface ManifestSnapshot {
|
||||
manifest: Manifest;
|
||||
diffs: ManifestDiff[];
|
||||
}
|
||||
const manifestsEqual = (manifest1: ManifestSchema, manifest2: ManifestSchema) =>
|
||||
isEqual(new Set(getArtifactIds(manifest1)), new Set(getArtifactIds(manifest2)));
|
||||
|
||||
export class ManifestManager {
|
||||
protected artifactClient: ArtifactClient;
|
||||
|
@ -209,8 +214,7 @@ export class ManifestManager {
|
|||
*/
|
||||
public async getLastComputedManifest(): Promise<Manifest | null> {
|
||||
try {
|
||||
const manifestClient = this.getManifestClient();
|
||||
const manifestSo = await manifestClient.getManifest();
|
||||
const manifestSo = await this.getManifestClient().getManifest();
|
||||
|
||||
if (manifestSo.version === undefined) {
|
||||
throw new Error('No version returned for manifest.');
|
||||
|
@ -222,14 +226,17 @@ export class ManifestManager {
|
|||
soVersion: manifestSo.version,
|
||||
});
|
||||
|
||||
for (const id of manifestSo.attributes.ids) {
|
||||
const artifactSo = await this.artifactClient.getArtifact(id);
|
||||
manifest.addEntry(artifactSo.attributes);
|
||||
for (const entry of manifestSo.attributes.artifacts) {
|
||||
manifest.addEntry(
|
||||
(await this.artifactClient.getArtifact(entry.artifactId)).attributes,
|
||||
entry.policyId
|
||||
);
|
||||
}
|
||||
|
||||
return manifest;
|
||||
} catch (err) {
|
||||
if (err.output.statusCode !== 404) {
|
||||
throw err;
|
||||
} catch (error) {
|
||||
if (!error.output || error.output.statusCode !== 404) {
|
||||
throw error;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -241,17 +248,36 @@ export class ManifestManager {
|
|||
* @param baselineManifest A baseline manifest to use for initializing pre-existing artifacts.
|
||||
* @returns {Promise<Manifest>} A new Manifest object reprenting the current exception list.
|
||||
*/
|
||||
public async buildNewManifest(baselineManifest?: Manifest): Promise<Manifest> {
|
||||
public async buildNewManifest(
|
||||
baselineManifest: Manifest = Manifest.getDefault(this.schemaVersion)
|
||||
): Promise<Manifest> {
|
||||
// Build new exception list artifacts
|
||||
const artifacts = (
|
||||
await Promise.all([this.buildExceptionListArtifacts(), this.buildTrustedAppsArtifacts()])
|
||||
).flat();
|
||||
|
||||
// Build new manifest
|
||||
const manifest = Manifest.fromArtifacts(
|
||||
artifacts,
|
||||
baselineManifest ?? Manifest.getDefault(this.schemaVersion)
|
||||
);
|
||||
const manifest = new Manifest({
|
||||
schemaVersion: this.schemaVersion,
|
||||
semanticVersion: baselineManifest.getSemanticVersion(),
|
||||
soVersion: baselineManifest.getSavedObjectVersion(),
|
||||
});
|
||||
|
||||
for (const artifact of artifacts) {
|
||||
let artifactToAdd = baselineManifest.getArtifact(getArtifactId(artifact)) || artifact;
|
||||
|
||||
if (!isCompressed(artifactToAdd)) {
|
||||
artifactToAdd = await maybeCompressArtifact(artifactToAdd);
|
||||
|
||||
if (!isCompressed(artifactToAdd)) {
|
||||
throw new Error(`Unable to compress artifact: ${getArtifactId(artifactToAdd)}`);
|
||||
} else if (!internalArtifactCompleteSchema.is(artifactToAdd)) {
|
||||
throw new Error(`Incomplete artifact detected: ${getArtifactId(artifactToAdd)}`);
|
||||
}
|
||||
}
|
||||
|
||||
manifest.addEntry(artifactToAdd);
|
||||
}
|
||||
|
||||
return manifest;
|
||||
}
|
||||
|
@ -264,35 +290,24 @@ export class ManifestManager {
|
|||
* @returns {Promise<Error[]>} Any errors encountered.
|
||||
*/
|
||||
public async tryDispatch(manifest: Manifest): Promise<Error[]> {
|
||||
const serializedManifest = manifest.toEndpointFormat();
|
||||
if (!manifestDispatchSchema.is(serializedManifest)) {
|
||||
return [new Error('Invalid manifest')];
|
||||
}
|
||||
|
||||
let paging = true;
|
||||
let page = 1;
|
||||
const errors: Error[] = [];
|
||||
|
||||
while (paging) {
|
||||
const { items, total } = await this.packagePolicyService.list(this.savedObjectsClient, {
|
||||
page,
|
||||
perPage: 20,
|
||||
kuery: 'ingest-package-policies.package.name:endpoint',
|
||||
});
|
||||
await this.forEachPolicy(async (packagePolicy) => {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const { id, revision, updated_at, updated_by, ...newPackagePolicy } = packagePolicy;
|
||||
if (newPackagePolicy.inputs.length > 0 && newPackagePolicy.inputs[0].config !== undefined) {
|
||||
const oldManifest = newPackagePolicy.inputs[0].config.artifact_manifest ?? {
|
||||
value: {},
|
||||
};
|
||||
|
||||
for (const packagePolicy of items) {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const { id, revision, updated_at, updated_by, ...newPackagePolicy } = packagePolicy;
|
||||
if (newPackagePolicy.inputs.length > 0 && newPackagePolicy.inputs[0].config !== undefined) {
|
||||
const oldManifest = newPackagePolicy.inputs[0].config.artifact_manifest ?? {
|
||||
value: {},
|
||||
};
|
||||
const newManifestVersion = manifest.getSemanticVersion();
|
||||
if (semver.gt(newManifestVersion, oldManifest.value.manifest_version)) {
|
||||
const serializedManifest = manifest.toPackagePolicyManifest(packagePolicy.id);
|
||||
|
||||
const newManifestVersion = manifest.getSemanticVersion();
|
||||
if (semver.gt(newManifestVersion, oldManifest.value.manifest_version)) {
|
||||
newPackagePolicy.inputs[0].config.artifact_manifest = {
|
||||
value: serializedManifest,
|
||||
};
|
||||
if (!manifestDispatchSchema.is(serializedManifest)) {
|
||||
errors.push(new Error(`Invalid manifest for policy ${packagePolicy.id}`));
|
||||
} else if (!manifestsEqual(serializedManifest, oldManifest.value)) {
|
||||
newPackagePolicy.inputs[0].config.artifact_manifest = { value: serializedManifest };
|
||||
|
||||
try {
|
||||
await this.packagePolicyService.update(
|
||||
|
@ -309,15 +324,17 @@ export class ManifestManager {
|
|||
errors.push(err);
|
||||
}
|
||||
} else {
|
||||
this.logger.debug(`No change in package policy: ${id}`);
|
||||
this.logger.debug(
|
||||
`No change in manifest content for package policy: ${id}. Staying on old version`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
errors.push(new Error(`Package Policy ${id} has no config.`));
|
||||
this.logger.debug(`No change in manifest version for package policy: ${id}`);
|
||||
}
|
||||
} else {
|
||||
errors.push(new Error(`Package Policy ${id} has no config.`));
|
||||
}
|
||||
paging = (page - 1) * 20 + items.length < total;
|
||||
page++;
|
||||
}
|
||||
});
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
@ -328,27 +345,41 @@ export class ManifestManager {
|
|||
* @param manifest The Manifest to commit.
|
||||
* @returns {Promise<Error | null>} An error, if encountered, or null.
|
||||
*/
|
||||
public async commit(manifest: Manifest): Promise<Error | null> {
|
||||
try {
|
||||
const manifestClient = this.getManifestClient();
|
||||
public async commit(manifest: Manifest) {
|
||||
const manifestClient = this.getManifestClient();
|
||||
|
||||
// Commit the new manifest
|
||||
const manifestSo = manifest.toSavedObject();
|
||||
const version = manifest.getSavedObjectVersion();
|
||||
// Commit the new manifest
|
||||
const manifestSo = manifest.toSavedObject();
|
||||
const version = manifest.getSavedObjectVersion();
|
||||
|
||||
if (version == null) {
|
||||
await manifestClient.createManifest(manifestSo);
|
||||
} else {
|
||||
await manifestClient.updateManifest(manifestSo, {
|
||||
version,
|
||||
});
|
||||
}
|
||||
|
||||
this.logger.info(`Committed manifest ${manifest.getSemanticVersion()}`);
|
||||
} catch (err) {
|
||||
return err;
|
||||
if (version == null) {
|
||||
await manifestClient.createManifest(manifestSo);
|
||||
} else {
|
||||
await manifestClient.updateManifest(manifestSo, {
|
||||
version,
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
this.logger.info(`Committed manifest ${manifest.getSemanticVersion()}`);
|
||||
}
|
||||
|
||||
private async forEachPolicy(callback: (policy: PackagePolicy) => Promise<void>) {
|
||||
let paging = true;
|
||||
let page = 1;
|
||||
|
||||
while (paging) {
|
||||
const { items, total } = await this.packagePolicyService.list(this.savedObjectsClient, {
|
||||
page,
|
||||
perPage: 20,
|
||||
kuery: 'ingest-package-policies.package.name:endpoint',
|
||||
});
|
||||
|
||||
for (const packagePolicy of items) {
|
||||
await callback(packagePolicy);
|
||||
}
|
||||
|
||||
paging = (page - 1) * 20 + items.length < total;
|
||||
page++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ import { registerPolicyRoutes } from './endpoint/routes/policy';
|
|||
import { ArtifactClient, ManifestManager } from './endpoint/services';
|
||||
import { EndpointAppContextService } from './endpoint/endpoint_app_context_services';
|
||||
import { EndpointAppContext } from './endpoint/types';
|
||||
import { registerDownloadExceptionListRoute } from './endpoint/routes/artifacts';
|
||||
import { registerDownloadArtifactRoute } from './endpoint/routes/artifacts';
|
||||
import { initUsageCollectors } from './usage';
|
||||
import type { SecuritySolutionRequestHandlerContext } from './types';
|
||||
import { registerTrustedAppsRoutes } from './endpoint/routes/trusted_apps';
|
||||
|
@ -130,7 +130,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
|
|||
private policyWatcher?: PolicyWatcher;
|
||||
|
||||
private manifestTask: ManifestTask | undefined;
|
||||
private exceptionsCache: LRU<string, Buffer>;
|
||||
private artifactsCache: LRU<string, Buffer>;
|
||||
|
||||
constructor(context: PluginInitializerContext) {
|
||||
this.context = context;
|
||||
|
@ -138,7 +138,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
|
|||
this.config = createConfig(context);
|
||||
this.appClientFactory = new AppClientFactory();
|
||||
// Cache up to three artifacts with a max retention of 5 mins each
|
||||
this.exceptionsCache = new LRU<string, Buffer>({ max: 3, maxAge: 1000 * 60 * 5 });
|
||||
this.artifactsCache = new LRU<string, Buffer>({ max: 3, maxAge: 1000 * 60 * 5 });
|
||||
this.telemetryEventsSender = new TelemetryEventsSender(this.logger);
|
||||
|
||||
this.logger.debug('plugin initialized');
|
||||
|
@ -192,7 +192,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
|
|||
registerResolverRoutes(router, endpointContext);
|
||||
registerPolicyRoutes(router, endpointContext);
|
||||
registerTrustedAppsRoutes(router, endpointContext);
|
||||
registerDownloadExceptionListRoute(router, endpointContext, this.exceptionsCache);
|
||||
registerDownloadArtifactRoute(router, endpointContext, this.artifactsCache);
|
||||
|
||||
plugins.features.registerKibanaFeature({
|
||||
id: SERVER_APP_ID,
|
||||
|
@ -337,7 +337,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
|
|||
exceptionListClient,
|
||||
packagePolicyService: plugins.fleet.packagePolicyService,
|
||||
logger: this.logger,
|
||||
cache: this.exceptionsCache,
|
||||
cache: this.artifactsCache,
|
||||
});
|
||||
|
||||
if (this.manifestTask) {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
"core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724",
|
||||
"dashboard": "40554caf09725935e2c02e02563a2d07",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"enterprise_search_telemetry": "3d1b76c39bfb2cc8296b024d73854724",
|
||||
"epm-packages": "2b83397e3eaaaa8ef15e38813f3721c3",
|
||||
"exception-list": "67f055ab8c10abd7b2ebfd969b836788",
|
||||
|
@ -818,16 +818,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -22352,4 +22361,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
"url": "c7f66a0df8b1b52f17c28c4adb111105",
|
||||
"enterprise_search_telemetry": "3d1b76c39bfb2cc8296b024d73854724",
|
||||
"hidden-saved-object-with-secret": "bdf31541e7d2f348b5e21a7769c022ba",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"migrationVersion": "4a1746014a75ade3a714e1db5763276f",
|
||||
"index-pattern": "45915a1ad866812242df474eb0479052",
|
||||
"fleet-agents": "cb661e8ede2b640c42c8e5ef99db0683",
|
||||
|
@ -700,16 +700,25 @@
|
|||
"type": "date",
|
||||
"index": false
|
||||
},
|
||||
"ids": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "d00f614b29a80360e1190193fd333bab",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"epm-packages": "8f6e0b09ea0374c4ffe98c3755373cff",
|
||||
"exception-list": "497afa2f881a675d72d58e20057f3d8b",
|
||||
"exception-list-agnostic": "497afa2f881a675d72d58e20057f3d8b",
|
||||
|
@ -666,16 +666,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2553,4 +2562,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "74eb4b909f81222fa1ddeaba2881a37e",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"epm-packages": "8f6e0b09ea0374c4ffe98c3755373cff",
|
||||
"exception-list": "497afa2f881a675d72d58e20057f3d8b",
|
||||
"exception-list-agnostic": "497afa2f881a675d72d58e20057f3d8b",
|
||||
|
@ -680,16 +680,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2677,4 +2686,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "40554caf09725935e2c02e02563a2d07",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"enterprise_search_telemetry": "3d1b76c39bfb2cc8296b024d73854724",
|
||||
"epm-packages": "2b83397e3eaaaa8ef15e38813f3721c3",
|
||||
"exception-list": "67f055ab8c10abd7b2ebfd969b836788",
|
||||
|
@ -752,16 +752,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2419,4 +2428,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "40554caf09725935e2c02e02563a2d07",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"enterprise_search_telemetry": "3d1b76c39bfb2cc8296b024d73854724",
|
||||
"epm-packages": "2b83397e3eaaaa8ef15e38813f3721c3",
|
||||
"exception-list": "67f055ab8c10abd7b2ebfd969b836788",
|
||||
|
@ -752,16 +752,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2419,4 +2428,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "d00f614b29a80360e1190193fd333bab",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"epm-packages": "8f6e0b09ea0374c4ffe98c3755373cff",
|
||||
"exception-list": "497afa2f881a675d72d58e20057f3d8b",
|
||||
"exception-list-agnostic": "497afa2f881a675d72d58e20057f3d8b",
|
||||
|
@ -666,16 +666,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2553,4 +2562,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
"core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724",
|
||||
"dashboard": "40554caf09725935e2c02e02563a2d07",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"enterprise_search_telemetry": "3d1b76c39bfb2cc8296b024d73854724",
|
||||
"epm-packages": "0cbbb16506734d341a96aaed65ec6413",
|
||||
"epm-packages-assets": "44621b2f6052ef966da47b7c3a00f33b",
|
||||
|
@ -832,16 +832,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -60,9 +60,13 @@
|
|||
"created": 1593183699663,
|
||||
"schemaVersion": "v1",
|
||||
"semanticVersion": "1.0.1",
|
||||
"ids": [
|
||||
"endpoint-exceptionlist-macos-v1-d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658",
|
||||
"endpoint-exceptionlist-windows-v1-8d2bcc37e82fad5d06e2c9e4bd96793ea8905ace1d528a57d0d0579ecc8c647e"
|
||||
"artifacts": [
|
||||
{
|
||||
"artifactId": "endpoint-exceptionlist-macos-v1-d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658"
|
||||
},
|
||||
{
|
||||
"artifactId": "endpoint-exceptionlist-windows-v1-8d2bcc37e82fad5d06e2c9e4bd96793ea8905ace1d528a57d0d0579ecc8c647e"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "endpoint:user-artifact-manifest",
|
||||
|
@ -211,4 +215,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "d00f614b29a80360e1190193fd333bab",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"epm-packages": "8f6e0b09ea0374c4ffe98c3755373cff",
|
||||
"exception-list": "497afa2f881a675d72d58e20057f3d8b",
|
||||
"exception-list-agnostic": "497afa2f881a675d72d58e20057f3d8b",
|
||||
|
@ -661,16 +661,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2584,4 +2593,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "d00f614b29a80360e1190193fd333bab",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"epm-packages": "8f6e0b09ea0374c4ffe98c3755373cff",
|
||||
"exception-list": "497afa2f881a675d72d58e20057f3d8b",
|
||||
"exception-list-agnostic": "497afa2f881a675d72d58e20057f3d8b",
|
||||
|
@ -666,16 +666,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2589,4 +2598,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "d00f614b29a80360e1190193fd333bab",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"epm-packages": "8f6e0b09ea0374c4ffe98c3755373cff",
|
||||
"exception-list": "497afa2f881a675d72d58e20057f3d8b",
|
||||
"exception-list-agnostic": "497afa2f881a675d72d58e20057f3d8b",
|
||||
|
@ -666,16 +666,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2589,4 +2598,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "d00f614b29a80360e1190193fd333bab",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"epm-packages": "8f6e0b09ea0374c4ffe98c3755373cff",
|
||||
"exception-list": "497afa2f881a675d72d58e20057f3d8b",
|
||||
"exception-list-agnostic": "497afa2f881a675d72d58e20057f3d8b",
|
||||
|
@ -666,16 +666,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2589,4 +2598,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "d00f614b29a80360e1190193fd333bab",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"epm-packages": "8f6e0b09ea0374c4ffe98c3755373cff",
|
||||
"exception-list": "497afa2f881a675d72d58e20057f3d8b",
|
||||
"exception-list-agnostic": "497afa2f881a675d72d58e20057f3d8b",
|
||||
|
@ -661,16 +661,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2584,4 +2593,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "d00f614b29a80360e1190193fd333bab",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"epm-packages": "8f6e0b09ea0374c4ffe98c3755373cff",
|
||||
"exception-list": "497afa2f881a675d72d58e20057f3d8b",
|
||||
"exception-list-agnostic": "497afa2f881a675d72d58e20057f3d8b",
|
||||
|
@ -661,16 +661,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2584,4 +2593,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "d00f614b29a80360e1190193fd333bab",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"epm-packages": "8f6e0b09ea0374c4ffe98c3755373cff",
|
||||
"exception-list": "497afa2f881a675d72d58e20057f3d8b",
|
||||
"exception-list-agnostic": "497afa2f881a675d72d58e20057f3d8b",
|
||||
|
@ -661,16 +661,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2584,4 +2593,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "40554caf09725935e2c02e02563a2d07",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"enterprise_search_telemetry": "3d1b76c39bfb2cc8296b024d73854724",
|
||||
"epm-packages": "2b83397e3eaaaa8ef15e38813f3721c3",
|
||||
"event_log_test": "bef808d4a9c27f204ffbda3359233931",
|
||||
|
@ -573,4 +573,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
"ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3",
|
||||
"ingest-agent-policies": "9326f99c977fd2ef5ab24b6336a0675c",
|
||||
"url": "c7f66a0df8b1b52f17c28c4adb111105",
|
||||
"endpoint:user-artifact-manifest": "67c28185da541c1404e7852d30498cd6",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"migrationVersion": "4a1746014a75ade3a714e1db5763276f",
|
||||
"index-pattern": "66eccb05066c5a89924f48a9e9736499",
|
||||
"fleet-agents": "034346488514b7058a79140b19ddf631",
|
||||
|
@ -659,9 +659,25 @@
|
|||
"type": "date",
|
||||
"index": false
|
||||
},
|
||||
"ids": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "d00f614b29a80360e1190193fd333bab",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "67c28185da541c1404e7852d30498cd6",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"epm-packages": "8f6e0b09ea0374c4ffe98c3755373cff",
|
||||
"exception-list": "4818e7dfc3e538562c80ec34eb6f841b",
|
||||
"exception-list-agnostic": "4818e7dfc3e538562c80ec34eb6f841b",
|
||||
|
@ -656,9 +656,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
"core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724",
|
||||
"dashboard": "40554caf09725935e2c02e02563a2d07",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"enterprise_search_telemetry": "3d1b76c39bfb2cc8296b024d73854724",
|
||||
"epm-packages": "0cbbb16506734d341a96aaed65ec6413",
|
||||
"epm-packages-assets": "44621b2f6052ef966da47b7c3a00f33b",
|
||||
|
@ -876,16 +876,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2718,4 +2727,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "74eb4b909f81222fa1ddeaba2881a37e",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"epm-packages": "386dc9996a3b74607de64c2ab2171582",
|
||||
"exception-list": "497afa2f881a675d72d58e20057f3d8b",
|
||||
"exception-list-agnostic": "497afa2f881a675d72d58e20057f3d8b",
|
||||
|
@ -704,16 +704,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2632,4 +2641,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
"config": "c63748b75f39d0c54de12d12c1ccbc20",
|
||||
"dashboard": "40554caf09725935e2c02e02563a2d07",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"enterprise_search_telemetry": "3d1b76c39bfb2cc8296b024d73854724",
|
||||
"epm-packages": "2b83397e3eaaaa8ef15e38813f3721c3",
|
||||
"event_log_test": "bef808d4a9c27f204ffbda3359233931",
|
||||
|
@ -222,4 +222,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
"core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724",
|
||||
"dashboard": "40554caf09725935e2c02e02563a2d07",
|
||||
"endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0",
|
||||
"endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d",
|
||||
"endpoint:user-artifact-manifest": "a0d7b04ad405eed54d76e279c3727862",
|
||||
"enterprise_search_telemetry": "3d1b76c39bfb2cc8296b024d73854724",
|
||||
"epm-packages": "0cbbb16506734d341a96aaed65ec6413",
|
||||
"epm-packages-assets": "44621b2f6052ef966da47b7c3a00f33b",
|
||||
|
@ -814,16 +814,25 @@
|
|||
"index": false,
|
||||
"type": "date"
|
||||
},
|
||||
"ids": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"schemaVersion": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"semanticVersion": {
|
||||
"index": false,
|
||||
"type": "keyword"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
},
|
||||
"artifactId": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2667,4 +2676,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue