Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SIEM][Security Solution][Endpoint] Endpoint Artifact Manifest Management + Artifact Download and Distribution #67707

Merged
merged 133 commits into from
Jul 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
133 commits
Select commit Hold shift + click to select a range
a466281
stub out task for the exceptions list packager
madirey May 28, 2020
ba1f2e7
Hits list code and pages
May 28, 2020
9464711
refactor
madirey May 28, 2020
076fa7a
Begin adding saved object and type definitions
madirey May 28, 2020
1a0e24f
Transforms to endpoint exceptions
May 28, 2020
82a1de1
Get internal SO client
madirey May 28, 2020
5590765
update messaging
madirey May 28, 2020
81d9a83
cleanup
madirey May 28, 2020
33eea04
Integrating with task manager
May 29, 2020
e8cef9a
Integrated with task manager properly
May 29, 2020
b9e478c
Begin adding schemas
madirey May 29, 2020
f2e6b16
Add multiple OS and schema version support
madirey Jun 3, 2020
184143e
filter by OS
madirey Jun 3, 2020
ac70535
Fixing sort
Jun 3, 2020
11e56d0
Move to security_solutions
madirey Jun 4, 2020
e304959
siem -> securitySolution
madirey Jun 4, 2020
3288bda
Progress on downloads, cleanup
Jun 4, 2020
e33563f
Add config, update artifact creation, add TODOs
madirey Jun 8, 2020
49f918d
Fixing buffer serialization problem
Jun 8, 2020
6a44082
Adding cleanup to task
Jun 8, 2020
62079c7
Handle HEAD req
Jun 8, 2020
502fd5e
proper header
Jun 8, 2020
4156900
More robust task management
madirey Jun 8, 2020
2d21723
single -> agnostic
Jun 8, 2020
86732e2
Fix OS filtering
madirey Jun 8, 2020
a15566e
Scaffolding digital signatures / tests
madirey Jun 9, 2020
0dbb443
Adds rotue for creating endpoint user
Jun 10, 2020
47ccc35
Cleanup
Jun 10, 2020
4b8aa0c
persisting user
Jun 10, 2020
2279695
Merge pull request #4 from madirey/exception-list-packager-rebased
Jun 11, 2020
056f377
Adding route to fetch created user
Jun 11, 2020
628d6a8
Addings tests for translating exceptions
Jun 12, 2020
f33b78c
sync master
madirey Jun 15, 2020
ab7e326
Adding test for download API
Jun 15, 2020
81b2aa9
Merge branch 'exception-list-packager' of github.com:madirey/kibana i…
madirey Jun 16, 2020
e1cba52
Download tweaks + artifact generation fixes
madirey Jun 17, 2020
2e8d58b
reorganize
madirey Jun 17, 2020
f8f5cae
Merge branch 'master' of https://github.com/elastic/kibana into excep…
madirey Jun 17, 2020
9cb08f1
fix imports
madirey Jun 17, 2020
978df5a
Fixing test
Jun 17, 2020
288407e
Changes id of SO
Jun 17, 2020
2459a3e
integration tests setup
madirey Jun 17, 2020
857a63d
Merge branch 'exception-list-packager' of github.com:madirey/kibana i…
madirey Jun 17, 2020
83ab609
Add first integration tests
madirey Jun 17, 2020
067201d
Cache layer
Jun 17, 2020
8e7f714
Merge branch 'exception-list-packager' of github.com:madirey/kibana i…
Jun 17, 2020
2c5d01b
more schema validation
madirey Jun 17, 2020
35aaa0e
fix conflicts
madirey Jun 17, 2020
849336c
Set up for manifest update
madirey Jun 18, 2020
40501cd
minor change
madirey Jun 18, 2020
680e425
remove setup code
madirey Jun 18, 2020
0eae6d8
add manifest schema
madirey Jun 18, 2020
80c0b4f
refactoring
madirey Jun 18, 2020
06007f4
manifest rewrite (partial)
madirey Jun 18, 2020
75449fb
finish scaffolding new manifest logic
madirey Jun 19, 2020
a83dfcd
syntax errors
madirey Jun 19, 2020
3e9e557
more refactoring
madirey Jun 20, 2020
3d325e2
Move to endpoint directory
madirey Jun 21, 2020
8929bc9
minor cleanup
madirey Jun 21, 2020
3f861ab
clean up old artifacts
madirey Jun 21, 2020
f61de08
Use diff appropriately
madirey Jun 21, 2020
2e1dc73
Fix download
madirey Jun 22, 2020
b0734c7
schedule task on interval
madirey Jun 22, 2020
f292347
Split up into client/manager
madirey Jun 23, 2020
d94ac6e
more mocks
madirey Jun 23, 2020
a94436f
config interval
madirey Jun 23, 2020
a4acdc0
Fixing download tests and adding cache tests
Jun 23, 2020
9d8b7b7
lint
Jun 23, 2020
9bd4b4c
mo money, mo progress
madirey Jun 23, 2020
797f244
Merge branch 'exception-list-packager' of github.com:madirey/kibana i…
madirey Jun 23, 2020
bc6a91b
sync master
madirey Jun 23, 2020
e7f28b5
Converting to io-ts
Jun 23, 2020
e906a8d
Merge branch 'master' of github.com:elastic/kibana into exception-lis…
madirey Jun 23, 2020
da80279
More tests and mocks
madirey Jun 24, 2020
2e6e651
even more tests and mocks
madirey Jun 24, 2020
673f35b
Merging both refactors
Jun 24, 2020
53df066
Adding more tests for the convertion layer
Jun 24, 2020
d7fa7b9
fix conflicts
madirey Jun 24, 2020
44da0a5
Adding lzma types
Jun 24, 2020
18a459b
Merge branch 'master' of github.com:elastic/kibana into exception-lis…
madirey Jun 24, 2020
7ce4f28
Bug fixes
madirey Jun 24, 2020
7fac32b
Merge branch 'exception-list-packager' of github.com:madirey/kibana i…
madirey Jun 24, 2020
2a6103f
lint
Jun 24, 2020
5a52d1b
resolve some type errors
madirey Jun 24, 2020
2e59e15
Adding back in cache
Jun 24, 2020
8e724ba
merging
Jun 24, 2020
d6d58c9
Fixing download test
Jun 24, 2020
d23a7bb
Changing cache to be sized
Jun 24, 2020
dee0506
Merging with upstream
Jun 24, 2020
e560082
Fix manifest manager initialization
madirey Jun 24, 2020
df06ecc
Hook up datasource service
madirey Jun 25, 2020
acaa5f4
Fix download tests
madirey Jun 25, 2020
e7b229d
Incremental progress
madirey Jun 25, 2020
53bb504
Adds integration with ingest manager for auth
Jun 25, 2020
82a4c41
Merge branch 'exception-list-packager' of github.com:madirey/kibana i…
madirey Jun 25, 2020
0ec461a
Update test fixture
madirey Jun 25, 2020
484ad99
Add manifest dispatch
madirey Jun 26, 2020
16d68a6
Refactoring to use the same SO Client from ingest
Jun 26, 2020
a8c3a40
bug fixes
madirey Jun 26, 2020
afb0003
Merge branch 'exception-list-packager' of github.com:madirey/kibana i…
madirey Jun 26, 2020
5f2e539
build renovate config
madirey Jun 26, 2020
346955e
Merge branch 'master' of github.com:elastic/kibana into exception-lis…
madirey Jun 26, 2020
6854602
Fix endpoint_app_context_services tests
madirey Jun 26, 2020
536a3b2
Only index the fields that are necessary for searching
madirey Jun 26, 2020
4356e08
Integ test progress
Jun 26, 2020
7f8d9d8
mock and test city
madirey Jun 26, 2020
6544b0d
Add task tests
madirey Jun 28, 2020
7f02443
Tests for artifact_client and manifest_client
madirey Jun 28, 2020
2c8a536
Add manifest_manager tests
madirey Jun 29, 2020
da0b32f
minor refactor
madirey Jun 29, 2020
8ee1ee4
Merge branch 'master' of github.com:elastic/kibana into exception-lis…
madirey Jun 29, 2020
843f874
Finish manifest_manager tests
madirey Jun 29, 2020
0c46e88
Type errors
madirey Jun 29, 2020
58f3f6f
Merge branch 'exception-list-packager' of github.com:madirey/kibana i…
Jun 29, 2020
b196bdd
Merge branch 'exception-list-packager' of github.com:madirey/kibana i…
Jun 29, 2020
3c09d7b
Update integ test
Jun 29, 2020
5e0d62f
Type errors, final cleanup
madirey Jun 30, 2020
3510dee
fix conflicts
madirey Jun 30, 2020
c0bf1f1
sync master
madirey Jun 30, 2020
67d756a
Fix integration test and add test for invalid api key
madirey Jun 30, 2020
343f515
Merge branch 'master' of github.com:elastic/kibana into exception-lis…
madirey Jun 30, 2020
eae1639
minor fixup
madirey Jun 30, 2020
77ffeb7
Remove compression
madirey Jul 1, 2020
2d904fb
Merge branch 'master' of github.com:elastic/kibana into exception-lis…
madirey Jul 1, 2020
975839e
Update task interval
madirey Jul 1, 2020
ddafd30
Removing .text suffix from translated list
Jul 1, 2020
2f74e05
Fixes hashes for unit tests
Jul 1, 2020
d517fea
clean up yarn.lock
madirey Jul 1, 2020
287222c
Merge branch 'exception-list-packager' of github.com:madirey/kibana i…
madirey Jul 1, 2020
3ed5c48
Remove lzma-native from package.json
madirey Jul 1, 2020
0ec1f2b
missed updating one of the tests
madirey Jul 1, 2020
f843f70
Fix conflicts
madirey Jul 2, 2020
80bb579
Merge branch 'master' of github.com:elastic/kibana into exception-lis…
madirey Jul 2, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion x-pack/plugins/lists/server/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ const createSetupMock = (): jest.Mocked<ListPluginSetup> => {

export const listMock = {
createSetup: createSetupMock,
getExceptionList: getExceptionListClientMock,
getExceptionListClient: getExceptionListClientMock,
getListClient: getListClientMock,
};
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,13 @@ export class EndpointDocGenerator {
enabled: true,
streams: [],
config: {
artifact_manifest: {
value: {
manifest_version: 'v0',
schema_version: '1.0.0',
artifacts: {},
},
},
policy: {
value: policyFactory(),
},
Expand Down
22 changes: 22 additions & 0 deletions x-pack/plugins/security_solution/common/endpoint/schema/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import * as t from 'io-ts';

export const identifier = t.string;

export const manifestVersion = t.string;

export const manifestSchemaVersion = t.keyof({
'1.0.0': null,
});
export type ManifestSchemaVersion = t.TypeOf<typeof manifestSchemaVersion>;

export const sha256 = t.string;

export const size = t.number;

export const url = t.string;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import * as t from 'io-ts';
import { identifier, manifestSchemaVersion, manifestVersion, sha256, size, url } from './common';

export const manifestEntrySchema = t.exact(
t.type({
url,
sha256,
size,
})
);

export const manifestSchema = t.exact(
t.type({
manifest_version: manifestVersion,
schema_version: manifestSchemaVersion,
artifacts: t.record(identifier, manifestEntrySchema),
})
);

export type ManifestEntrySchema = t.TypeOf<typeof manifestEntrySchema>;
export type ManifestSchema = t.TypeOf<typeof manifestSchema>;
4 changes: 4 additions & 0 deletions x-pack/plugins/security_solution/common/endpoint/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

import { PackageConfig, NewPackageConfig } from '../../../ingest_manager/common';
import { ManifestSchema } from './schema/manifest';

/**
* Object that allows you to maintain stateful information in the location object across navigation events
Expand Down Expand Up @@ -691,6 +692,9 @@ export type NewPolicyData = NewPackageConfig & {
enabled: boolean;
streams: [];
config: {
artifact_manifest: {
value: ManifestSchema;
};
policy: {
value: PolicyConfig;
};
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/security_solution/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"features",
"home",
"ingestManager",
"taskManager",
"inspector",
"licensing",
"maps",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ describe('policy details: ', () => {
enabled: true,
streams: [],
config: {
artifact_manifest: {
value: {
manifest_version: 'v0',
schema_version: '1.0.0',
artifacts: {},
},
},
policy: {
value: policyConfigFactory(),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,23 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { httpServerMock } from '../../../../../src/core/server/mocks';
import { EndpointAppContextService } from './endpoint_app_context_services';

describe('test endpoint app context services', () => {
it('should throw error if start is not called', async () => {
it('should throw error on getAgentService if start is not called', async () => {
const endpointAppContextService = new EndpointAppContextService();
expect(() => endpointAppContextService.getAgentService()).toThrow(Error);
});
it('should return undefined on getManifestManager if start is not called', async () => {
const endpointAppContextService = new EndpointAppContextService();
expect(endpointAppContextService.getManifestManager()).toEqual(undefined);
});
it('should throw error on getScopedSavedObjectsClient if start is not called', async () => {
const endpointAppContextService = new EndpointAppContextService();
expect(() =>
endpointAppContextService.getScopedSavedObjectsClient(httpServerMock.createKibanaRequest())
).toThrow(Error);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,22 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import {
SavedObjectsServiceStart,
KibanaRequest,
SavedObjectsClientContract,
} from 'src/core/server';
import { AgentService, IngestManagerStartContract } from '../../../ingest_manager/server';
import { handlePackageConfigCreate } from './ingest_integration';
import { getPackageConfigCreateCallback } from './ingest_integration';
import { ManifestManager } from './services/artifacts';

export type EndpointAppContextServiceStartContract = Pick<
IngestManagerStartContract,
'agentService'
> & {
manifestManager?: ManifestManager | undefined;
registerIngestCallback: IngestManagerStartContract['registerExternalCallback'];
savedObjectsStart: SavedObjectsServiceStart;
};

/**
Expand All @@ -19,10 +27,20 @@ export type EndpointAppContextServiceStartContract = Pick<
*/
export class EndpointAppContextService {
private agentService: AgentService | undefined;
private manifestManager: ManifestManager | undefined;
private savedObjectsStart: SavedObjectsServiceStart | undefined;

public start(dependencies: EndpointAppContextServiceStartContract) {
this.agentService = dependencies.agentService;
dependencies.registerIngestCallback('packageConfigCreate', handlePackageConfigCreate);
this.manifestManager = dependencies.manifestManager;
this.savedObjectsStart = dependencies.savedObjectsStart;

if (this.manifestManager !== undefined) {
dependencies.registerIngestCallback(
'packageConfigCreate',
getPackageConfigCreateCallback(this.manifestManager)
);
}
}

public stop() {}
Expand All @@ -33,4 +51,15 @@ export class EndpointAppContextService {
}
return this.agentService;
}

public getManifestManager(): ManifestManager | undefined {
return this.manifestManager;
}

public getScopedSavedObjectsClient(req: KibanaRequest): SavedObjectsClientContract {
if (!this.savedObjectsStart) {
throw new Error(`must call start on ${EndpointAppContextService.name} to call getter`);
}
return this.savedObjectsStart.getScopedClient(req, { excludedWrappers: ['security'] });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,62 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { NewPackageConfig } from '../../../ingest_manager/common/types/models';
import { factory as policyConfigFactory } from '../../common/endpoint/models/policy_config';
import { NewPolicyData } from '../../common/endpoint/types';
import { NewPackageConfig } from '../../../ingest_manager/common/types/models';
import { ManifestManager } from './services/artifacts';

/**
* Callback to handle creation of package configs in Ingest Manager
* @param newPackageConfig
* Callback to handle creation of PackageConfigs in Ingest Manager
*/
export const handlePackageConfigCreate = async (
newPackageConfig: NewPackageConfig
): Promise<NewPackageConfig> => {
// We only care about Endpoint package configs
if (newPackageConfig.package?.name !== 'endpoint') {
return newPackageConfig;
}
export const getPackageConfigCreateCallback = (
manifestManager: ManifestManager
): ((newPackageConfig: NewPackageConfig) => Promise<NewPackageConfig>) => {
const handlePackageConfigCreate = async (
newPackageConfig: NewPackageConfig
): Promise<NewPackageConfig> => {
// We only care about Endpoint package configs
if (newPackageConfig.package?.name !== 'endpoint') {
return newPackageConfig;
}

// We cast the type here so that any changes to the Endpoint specific data
// follow the types/schema expected
let updatedPackageConfig = newPackageConfig as NewPolicyData;
// We cast the type here so that any changes to the Endpoint specific data
// follow the types/schema expected
let updatedPackageConfig = newPackageConfig as NewPolicyData;

// Until we get the Default Policy Configuration in the Endpoint package,
// we will add it here manually at creation time.
// @ts-ignore
if (newPackageConfig.inputs.length === 0) {
updatedPackageConfig = {
...newPackageConfig,
inputs: [
{
type: 'endpoint',
enabled: true,
streams: [],
config: {
policy: {
value: policyConfigFactory(),
const wrappedManifest = await manifestManager.refresh({ initialize: true });
if (wrappedManifest !== null) {
// Until we get the Default Policy Configuration in the Endpoint package,
// we will add it here manually at creation time.
// @ts-ignore
if (newPackageConfig.inputs.length === 0) {
updatedPackageConfig = {
...newPackageConfig,
inputs: [
{
type: 'endpoint',
enabled: true,
streams: [],
config: {
artifact_manifest: {
value: wrappedManifest.manifest.toEndpointFormat(),
},
policy: {
value: policyConfigFactory(),
},
},
},
},
},
],
};
}
],
};
}
}

try {
return updatedPackageConfig;
} finally {
await manifestManager.commit(wrappedManifest);
}
};

return updatedPackageConfig;
return handlePackageConfigCreate;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { ExceptionsCache } from './cache';

describe('ExceptionsCache tests', () => {
let cache: ExceptionsCache;

beforeEach(() => {
jest.clearAllMocks();
cache = new ExceptionsCache(3);
});

test('it should cache', async () => {
cache.set('test', 'body');
const cacheResp = cache.get('test');
expect(cacheResp).toEqual('body');
});

test('it should handle cache miss', async () => {
cache.set('test', 'body');
const cacheResp = cache.get('not test');
expect(cacheResp).toEqual(undefined);
});

test('it should handle cache eviction', async () => {
cache.set('1', 'a');
cache.set('2', 'b');
cache.set('3', 'c');
const cacheResp = cache.get('1');
expect(cacheResp).toEqual('a');

cache.set('4', 'd');
const secondResp = cache.get('1');
expect(secondResp).toEqual(undefined);
expect(cache.get('2')).toEqual('b');
expect(cache.get('3')).toEqual('c');
expect(cache.get('4')).toEqual('d');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

const DEFAULT_MAX_SIZE = 10;

/**
* FIFO cache implementation for artifact downloads.
*/
export class ExceptionsCache {
private cache: Map<string, string>;
private queue: string[];
private maxSize: number;

constructor(maxSize: number) {
this.cache = new Map();
this.queue = [];
this.maxSize = maxSize || DEFAULT_MAX_SIZE;
}

set(id: string, body: string) {
if (this.queue.length + 1 > this.maxSize) {
const entry = this.queue.shift();
if (entry !== undefined) {
this.cache.delete(entry);
}
}
this.queue.push(id);
this.cache.set(id, body);
}

get(id: string): string | undefined {
return this.cache.get(id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

export const ArtifactConstants = {
GLOBAL_ALLOWLIST_NAME: 'endpoint-exceptionlist',
SAVED_OBJECT_TYPE: 'endpoint:exceptions-artifact',
SUPPORTED_OPERATING_SYSTEMS: ['linux', 'macos', 'windows'],
SCHEMA_VERSION: '1.0.0',
};

export const ManifestConstants = {
SAVED_OBJECT_TYPE: 'endpoint:exceptions-manifest',
SCHEMA_VERSION: '1.0.0',
};
Loading