Skip to content

Commit

Permalink
[Security Solution][Endpoint] Allow wildcard in trusted app paths (#9…
Browse files Browse the repository at this point in the history
…7623) (#98749)

* show operator dropdown for path field

refs elastic/security-team/issues/543

* update translation to use consistent values

refs elastic/security-team/issues/543

* update schema to validate path values

refs elastic/security-team/issues/543

* add tests for field and operator values

refs elastic/security-team/issues/543

* review changes

refs elastic/security-team/issues/543

* update schema to enforce dropdown validation for PATH field

refs elastic/security-team/issues/543

* add tests for schema updates

refs 1deab39
refs elastic/security-team/issues/543

* optimise dropdown list for re-renders

refs elastic/security-team/issues/543

* align input fields and keep alignments when resized

refs elastic/security-team/issues/543

* correctly enter operator data on trusted app CRUD

refs elastic/security-team/issues/543

* update tests

refs 2ac56ee
refs elastic/security-team/issues/543

* remove redundant code

review changes

* better type assertion

review changes

* move operator options out of component

- these do not depend on component props and thus no need to have it within a useMemo callback.

- review changes

* derive keys from operator entry field

review changes

* update type

* use custom styles for aligning input fields

review changes

* add a custom type for trusted_apps operator

undo changes from list plugin and server/lib/detection_engine

refs 2ac56ee
refs elastic/security-team/issues/543

* add wildcard entry type

refs elastic/security-team/issues/543
refs #97623 (review)

* use the new entry type

refs elastic/security-team/issues/543
refs #97623 (review)

* update tests

refs elastic/security-team/issues/543
refs #97623 (review)

* update name for wildcard type so that it can be used also for cased inputs

refs elastic/security-team/issues/543
refs f9cb7ed

* update artifacts to support wildcard entries

refs elastic/security-team/issues/543

* add tests for list schemas

refs f9cb7ed
refs elastic/security-team/issues/543

* add placeholders for path values

review changes
/pull/97623#discussion_r620617999

* ignore type check for now

* add type assertion

refs 284352e

* remove unnecessary test

refs 2ac56ee

* fix types

refs f9cb7ed
refs b3f5dc4

* add a note to entries

review changes

refs dbd3532

* remove redundant type assertions

review changes
refs bcf615a
refs b3f5dc4

* move placeholder text logic to utils

review changes /pull/97623#discussion_r621673881

refs 6f2d0d7

* pass the style as prop

review changes

* update api doc

CI check suggestion

* make placeholderText a function expression

review suggestion

/pull/97623/commits/2dc4fd390cf5ea0e4fa67b3f5fc2561cbb29555e

* use semantic names for functions

refs 330731e

Co-authored-by: Kibana Machine <[email protected]>
# Conflicts:
#	api_docs/security_solution.json
  • Loading branch information
ashokaditya authored Apr 29, 2021
1 parent 6ab2912 commit ed51d31
Show file tree
Hide file tree
Showing 30 changed files with 678 additions and 97 deletions.
38 changes: 19 additions & 19 deletions api_docs/security_solution.json
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@
"description": [],
"source": {
"path": "x-pack/plugins/security_solution/public/plugin.tsx",
"lineNumber": 353
"lineNumber": 346
}
},
{
Expand All @@ -221,15 +221,15 @@
"description": [],
"source": {
"path": "x-pack/plugins/security_solution/public/plugin.tsx",
"lineNumber": 353
"lineNumber": 346
}
}
],
"tags": [],
"returnComment": [],
"source": {
"path": "x-pack/plugins/security_solution/public/plugin.tsx",
"lineNumber": 353
"lineNumber": 346
}
},
{
Expand All @@ -245,7 +245,7 @@
"returnComment": [],
"source": {
"path": "x-pack/plugins/security_solution/public/plugin.tsx",
"lineNumber": 398
"lineNumber": 391
}
}
],
Expand Down Expand Up @@ -276,7 +276,7 @@
"description": [],
"source": {
"path": "x-pack/plugins/security_solution/public/types.ts",
"lineNumber": 69
"lineNumber": 68
},
"signature": [
"() => Promise<",
Expand All @@ -287,7 +287,7 @@
],
"source": {
"path": "x-pack/plugins/security_solution/public/types.ts",
"lineNumber": 68
"lineNumber": 67
},
"lifecycle": "setup",
"initialIsOpen": true
Expand All @@ -301,7 +301,7 @@
"children": [],
"source": {
"path": "x-pack/plugins/security_solution/public/types.ts",
"lineNumber": 72
"lineNumber": 71
},
"lifecycle": "start",
"initialIsOpen": true
Expand Down Expand Up @@ -453,15 +453,15 @@
"description": [],
"source": {
"path": "x-pack/plugins/security_solution/server/plugin.ts",
"lineNumber": 147
"lineNumber": 145
}
}
],
"tags": [],
"returnComment": [],
"source": {
"path": "x-pack/plugins/security_solution/server/plugin.ts",
"lineNumber": 147
"lineNumber": 145
}
},
{
Expand Down Expand Up @@ -521,7 +521,7 @@
"description": [],
"source": {
"path": "x-pack/plugins/security_solution/server/plugin.ts",
"lineNumber": 159
"lineNumber": 157
}
},
{
Expand All @@ -535,15 +535,15 @@
"description": [],
"source": {
"path": "x-pack/plugins/security_solution/server/plugin.ts",
"lineNumber": 159
"lineNumber": 157
}
}
],
"tags": [],
"returnComment": [],
"source": {
"path": "x-pack/plugins/security_solution/server/plugin.ts",
"lineNumber": 159
"lineNumber": 157
}
},
{
Expand Down Expand Up @@ -582,7 +582,7 @@
"description": [],
"source": {
"path": "x-pack/plugins/security_solution/server/plugin.ts",
"lineNumber": 341
"lineNumber": 338
}
},
{
Expand All @@ -596,15 +596,15 @@
"description": [],
"source": {
"path": "x-pack/plugins/security_solution/server/plugin.ts",
"lineNumber": 341
"lineNumber": 338
}
}
],
"tags": [],
"returnComment": [],
"source": {
"path": "x-pack/plugins/security_solution/server/plugin.ts",
"lineNumber": 341
"lineNumber": 338
}
},
{
Expand All @@ -620,13 +620,13 @@
"returnComment": [],
"source": {
"path": "x-pack/plugins/security_solution/server/plugin.ts",
"lineNumber": 421
"lineNumber": 412
}
}
],
"source": {
"path": "x-pack/plugins/security_solution/server/plugin.ts",
"lineNumber": 131
"lineNumber": 129
},
"initialIsOpen": false
}
Expand Down Expand Up @@ -1484,7 +1484,7 @@
"children": [],
"source": {
"path": "x-pack/plugins/security_solution/server/plugin.ts",
"lineNumber": 107
"lineNumber": 105
},
"lifecycle": "setup",
"initialIsOpen": true
Expand All @@ -1498,7 +1498,7 @@
"children": [],
"source": {
"path": "x-pack/plugins/security_solution/server/plugin.ts",
"lineNumber": 110
"lineNumber": 108
},
"lifecycle": "start",
"initialIsOpen": true
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/lists/common/constants.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const OPERATOR_EXCLUDED = 'excluded';
export const ENTRY_VALUE = 'some host name';
export const MATCH = 'match';
export const MATCH_ANY = 'match_any';
export const WILDCARD = 'wildcard';
export const MAX_IMPORT_PAYLOAD_BYTES = 9000000;
export const IMPORT_BUFFER_SIZE = 1000;
export const LIST = 'list';
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/lists/common/schemas/common/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ export enum OperatorTypeEnum {
NESTED = 'nested',
MATCH = 'match',
MATCH_ANY = 'match_any',
WILDCARD = 'wildcard',
EXISTS = 'exists',
LIST = 'list',
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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 * as t from 'io-ts';

import { NonEmptyString } from '../../../shared_imports';
import { operatorIncluded } from '../../common/schemas';

export const endpointEntryMatchWildcard = t.exact(
t.type({
field: NonEmptyString,
operator: operatorIncluded,
type: t.keyof({ wildcard: null }),
value: NonEmptyString,
})
);
export type EndpointEntryMatchWildcard = t.TypeOf<typeof endpointEntryMatchWildcard>;
20 changes: 18 additions & 2 deletions x-pack/plugins/lists/common/schemas/types/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,28 @@ import { entriesMatch } from './entry_match';
import { entriesExists } from './entry_exists';
import { entriesList } from './entry_list';
import { entriesNested } from './entry_nested';
import { entriesMatchWildcard } from './entry_match_wildcard';

export const entry = t.union([entriesMatch, entriesMatchAny, entriesList, entriesExists]);
// NOTE: Type nested is not included here to denote it's non-recursive nature.
// So a nested entry is really just a collection of `Entry` types.
export const entry = t.union([
entriesMatch,
entriesMatchAny,
entriesList,
entriesExists,
entriesMatchWildcard,
]);
export type Entry = t.TypeOf<typeof entry>;

export const entriesArray = t.array(
t.union([entriesMatch, entriesMatchAny, entriesList, entriesExists, entriesNested])
t.union([
entriesMatch,
entriesMatchAny,
entriesList,
entriesExists,
entriesNested,
entriesMatchWildcard,
])
);
export type EntriesArray = t.TypeOf<typeof entriesArray>;

Expand Down
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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { ENTRY_VALUE, FIELD, OPERATOR, WILDCARD } from '../../constants.mock';

import { EntryMatchWildcard } from './entry_match_wildcard';

export const getEntryMatchWildcardMock = (): EntryMatchWildcard => ({
field: FIELD,
operator: OPERATOR,
type: WILDCARD,
value: ENTRY_VALUE,
});

export const getEntryMatchWildcardExcludeMock = (): EntryMatchWildcard => ({
...getEntryMatchWildcardMock(),
operator: 'excluded',
});
106 changes: 106 additions & 0 deletions x-pack/plugins/lists/common/schemas/types/entry_match_wildcard.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* 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 { pipe } from 'fp-ts/lib/pipeable';
import { left } from 'fp-ts/lib/Either';

import { foldLeftRight, getPaths } from '../../shared_imports';

import { getEntryMatchWildcardMock } from './entry_match_wildcard.mock';
import { EntryMatchWildcard, entriesMatchWildcard } from './entry_match_wildcard';

describe('entriesMatchWildcard', () => {
test('it should validate an entry', () => {
const payload = getEntryMatchWildcardMock();
const decoded = entriesMatchWildcard.decode(payload);
const message = pipe(decoded, foldLeftRight);

expect(getPaths(left(message.errors))).toEqual([]);
expect(message.schema).toEqual(payload);
});

test('it should validate when operator is "included"', () => {
const payload = getEntryMatchWildcardMock();
const decoded = entriesMatchWildcard.decode(payload);
const message = pipe(decoded, foldLeftRight);

expect(getPaths(left(message.errors))).toEqual([]);
expect(message.schema).toEqual(payload);
});

test('it should validate when "operator" is "excluded"', () => {
const payload = getEntryMatchWildcardMock();
payload.operator = 'excluded';
const decoded = entriesMatchWildcard.decode(payload);
const message = pipe(decoded, foldLeftRight);

expect(getPaths(left(message.errors))).toEqual([]);
expect(message.schema).toEqual(payload);
});

test('it should FAIL validation when "field" is empty string', () => {
const payload: Omit<EntryMatchWildcard, 'field'> & { field: string } = {
...getEntryMatchWildcardMock(),
field: '',
};
const decoded = entriesMatchWildcard.decode(payload);
const message = pipe(decoded, foldLeftRight);

expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "field"']);
expect(message.schema).toEqual({});
});

test('it should FAIL validation when "value" is not string', () => {
const payload: Omit<EntryMatchWildcard, 'value'> & { value: string[] } = {
...getEntryMatchWildcardMock(),
value: ['some value'],
};
const decoded = entriesMatchWildcard.decode(payload);
const message = pipe(decoded, foldLeftRight);

expect(getPaths(left(message.errors))).toEqual([
'Invalid value "["some value"]" supplied to "value"',
]);
expect(message.schema).toEqual({});
});

test('it should FAIL validation when "value" is empty string', () => {
const payload: Omit<EntryMatchWildcard, 'value'> & { value: string } = {
...getEntryMatchWildcardMock(),
value: '',
};
const decoded = entriesMatchWildcard.decode(payload);
const message = pipe(decoded, foldLeftRight);

expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "value"']);
expect(message.schema).toEqual({});
});

test('it should FAIL validation when "type" is not "wildcard"', () => {
const payload: Omit<EntryMatchWildcard, 'type'> & { type: string } = {
...getEntryMatchWildcardMock(),
type: 'match',
};
const decoded = entriesMatchWildcard.decode(payload);
const message = pipe(decoded, foldLeftRight);

expect(getPaths(left(message.errors))).toEqual(['Invalid value "match" supplied to "type"']);
expect(message.schema).toEqual({});
});

test('it should strip out extra keys', () => {
const payload: EntryMatchWildcard & {
extraKey?: string;
} = getEntryMatchWildcardMock();
payload.extraKey = 'some value';
const decoded = entriesMatchWildcard.decode(payload);
const message = pipe(decoded, foldLeftRight);

expect(getPaths(left(message.errors))).toEqual([]);
expect(message.schema).toEqual(getEntryMatchWildcardMock());
});
});
21 changes: 21 additions & 0 deletions x-pack/plugins/lists/common/schemas/types/entry_match_wildcard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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 * as t from 'io-ts';

import { NonEmptyString } from '../../shared_imports';
import { operator } from '../common/schemas';

export const entriesMatchWildcard = t.exact(
t.type({
field: NonEmptyString,
operator,
type: t.keyof({ wildcard: null }),
value: NonEmptyString,
})
);
export type EntryMatchWildcard = t.TypeOf<typeof entriesMatchWildcard>;
1 change: 1 addition & 0 deletions x-pack/plugins/lists/common/schemas/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export * from './default_namespace';
export * from './entries';
export * from './entry_match';
export * from './entry_match_any';
export * from './entry_match_wildcard';
export * from './entry_list';
export * from './entry_exists';
export * from './entry_nested';
Expand Down
Loading

0 comments on commit ed51d31

Please sign in to comment.