Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
127 commits
Select commit Hold shift + click to select a range
4d405a0
feat: add trusted devices feature flag and role
szwarckonrad Jul 22, 2025
254e119
feat: add dedicated product feature key for Trusted Devices management
szwarckonrad Jul 22, 2025
f1206c1
Merge branch 'main' into device-control-rbac
szwarckonrad Jul 22, 2025
b4a07ca
Merge branch 'main' into device-control-rbac
szwarckonrad Jul 23, 2025
b187040
Merge branch 'device-control-rbac' of https://github.com/szwarckonrad…
szwarckonrad Jul 23, 2025
168132c
Merge branch 'main' into device-control-rbac
szwarckonrad Jul 23, 2025
298cffc
feat: add USB device protection card with enterprise license check
szwarckonrad Jul 23, 2025
b231c5f
refactor: rename and update Device Control card component
szwarckonrad Jul 23, 2025
fabb491
Merge branch 'main' into device-control-rbac
szwarckonrad Jul 24, 2025
0662df5
Merge branch 'main' into device-control-rbac
szwarckonrad Jul 24, 2025
7c670d2
Merge branch 'main' into device-control-rbac
szwarckonrad Jul 24, 2025
8a42e2c
Merge branch 'refs/heads/main' into device-control-rbac
szwarckonrad Jul 25, 2025
a7a112f
feat: add device control settings to endpoint security policy
szwarckonrad Jul 25, 2025
9420353
feat: add device control settings to endpoint policy configuration
szwarckonrad Jul 25, 2025
a4a8dea
chore: remove legacy locked card upgrade message from translations
szwarckonrad Jul 25, 2025
8885331
Merge branch 'main' into device-control-rbac
szwarckonrad Jul 25, 2025
35cf852
feat: add device control license validation to endpoint policy config
szwarckonrad Jul 25, 2025
d6decda
Merge branch 'main' into device-control-rbac
szwarckonrad Jul 25, 2025
6708c91
Merge branch 'main' into device-control-rbac
szwarckonrad Jul 25, 2025
d0118aa
feat: add device control popup settings and update license checks to …
szwarckonrad Jul 25, 2025
9ac0f77
Merge branch 'main' into device-control-rbac
szwarckonrad Jul 28, 2025
7d0f505
feat: add trusted devices management functionality
szwarckonrad Jul 30, 2025
b94b6ca
Merge branch 'main' into device-control-manage
szwarckonrad Jul 30, 2025
9b21efe
Merge branch 'main' into device-control-rbac
szwarckonrad Jul 30, 2025
9988f8a
feat: add execute only access level to device control and update test…
szwarckonrad Jul 30, 2025
5ba098d
Merge branch 'main' into device-control-rbac
szwarckonrad Jul 30, 2025
c69573d
Merge branch 'main' into device-control-manage
szwarckonrad Jul 30, 2025
e84649a
feat: add endpoint_trusted_devices to detection alert schema and comm…
szwarckonrad Jul 30, 2025
c542419
[CI] Auto-commit changed files from 'yarn openapi:bundle'
kibanamachine Jul 30, 2025
546814d
[CI] Auto-commit changed files from 'make api-docs'
kibanamachine Jul 30, 2025
40946bd
[CI] Auto-commit changed files from 'yarn openapi:generate'
kibanamachine Jul 30, 2025
522fa33
feat: add trusted devices to endpoint artifact list types
szwarckonrad Jul 30, 2025
061df95
Merge branch 'main' into device-control-manage
szwarckonrad Jul 30, 2025
7d0503b
Merge branch 'main' into device-control-rbac
szwarckonrad Jul 30, 2025
03a4d9e
refactor: remove unnecessary comments from device control components
szwarckonrad Jul 30, 2025
6b588cb
Merge branch 'main' into device-control-rbac
szwarckonrad Jul 30, 2025
ff25c0b
fix: remove outdated upgrade messages from security solution endpoint…
szwarckonrad Jul 30, 2025
bc0737b
Merge branch 'device-control-manage' into device-control-combined
szwarckonrad Jul 30, 2025
4b06bf6
feat: add endpoint_trusted_devices to various lists and tests
szwarckonrad Jul 30, 2025
6bf163a
feat: add endpoint_trusted_devices to various lists and tests
szwarckonrad Jul 30, 2025
c05578e
Merge branch 'main' into device-control-combined
szwarckonrad Jul 31, 2025
b1d066f
Merge branch 'main' into device-control-combined
szwarckonrad Jul 31, 2025
867c16d
Trusted devices form component
szwarckonrad Jul 31, 2025
e87577c
Add TrustedDeviceConditionEntryField enum and update translations and…
szwarckonrad Aug 1, 2025
9137c88
Merge branch 'main' into device-control-combined
szwarckonrad Aug 1, 2025
a4c09d3
Merge branch 'main' into device-control-rbac
szwarckonrad Aug 1, 2025
3a797b8
Refactor TrustedDevicesApiClient to utilize separate transforms modul…
szwarckonrad Aug 1, 2025
5f54c99
Merge branch 'device-control-rbac' into device-control-manage
szwarckonrad Aug 1, 2025
5c69395
Merge device-control-rbac into device-control-combined
szwarckonrad Aug 1, 2025
74f2f5c
Add new translation for "Windows and Mac" and update OS selection in …
szwarckonrad Aug 1, 2025
9625f60
refactor: update device control access level labels for clarity
szwarckonrad Aug 1, 2025
14daca5
Merge branch 'main' into device-control-rbac
szwarckonrad Aug 1, 2025
807d7d5
refactor: update access level terminology in DeviceControlProtectionL…
szwarckonrad Aug 1, 2025
ae1b13d
Merge branch 'main' into device-control-rbac
szwarckonrad Aug 1, 2025
ea3b746
Merge branch 'main' into device-control-rbac
szwarckonrad Aug 4, 2025
4dcfe8a
Merge branch 'device-control-rbac' into device-control-manage
szwarckonrad Aug 4, 2025
b3f3e3d
Merge branch 'device-control-rbac' into device-control-combined
szwarckonrad Aug 4, 2025
071ba30
feat: add support for trusted devices with new schemas and artifact m…
szwarckonrad Aug 4, 2025
4b8b59d
cr
szwarckonrad Aug 4, 2025
3abead6
Merge branch 'main' into device-control-rbac
szwarckonrad Aug 4, 2025
b5b26b9
Merge branch 'device-control-rbac' into device-control-manage
szwarckonrad Aug 4, 2025
47915b2
Merge branch 'device-control-rbac' into device-control-combined
szwarckonrad Aug 4, 2025
d7aa239
fix: update experimental feature flag for trusted devices in subfeatu…
szwarckonrad Aug 4, 2025
1751538
Merge branch 'main' into device-control-manage
szwarckonrad Aug 5, 2025
eafc50e
Merge branch 'main' into device-control-manage
szwarckonrad Aug 5, 2025
cc8d208
Merge branch 'device-control-manage' of https://github.com/szwarckonr…
szwarckonrad Aug 5, 2025
e1464aa
Merge branch 'main' into device-control-combined
szwarckonrad Aug 5, 2025
4f4af33
Refactor trusted devices feature flag references to use unified key
szwarckonrad Aug 5, 2025
ad6858c
Merge branch 'main' into device-control-manage
szwarckonrad Aug 5, 2025
5baf52f
Merge branch 'device-control-manage' into device-control-combined
szwarckonrad Aug 5, 2025
a57b304
Merge branch 'device-control-combined' into device-control-artifacts
szwarckonrad Aug 5, 2025
c84c689
Fix TrustedDevicesArtifactCard to use correct artifacts path
szwarckonrad Aug 5, 2025
2629125
Merge branch 'main' into device-control-manage
szwarckonrad Aug 5, 2025
5786b57
Remove unused createEndpointTrustedDevicesList function and its refer…
szwarckonrad Aug 6, 2025
41a7afc
Merge branch 'main' into device-control-manage
szwarckonrad Aug 6, 2025
8cadd91
Merge branch 'device-control-manage' into device-control-combined
szwarckonrad Aug 6, 2025
d37c165
Merge branch 'device-control-combined' into device-control-artifacts
szwarckonrad Aug 6, 2025
fa311fd
Merge branch 'main' into device-control-manage
szwarckonrad Aug 7, 2025
099f6df
Update data-test-subj attribute in TrustedDevicesPolicyCard to "trust…
szwarckonrad Aug 7, 2025
5097bd3
Merge branch 'device-control-rbac' into device-control-combined
szwarckonrad Aug 7, 2025
dc0b1f8
Merge branch 'device-control-manage' into device-control-combined
szwarckonrad Aug 7, 2025
2cb9cc7
Merge branch 'device-control-combined' into device-control-artifacts
szwarckonrad Aug 7, 2025
efb0f1d
Merge branch 'main' into device-control-manage
szwarckonrad Aug 7, 2025
b05c3b9
Merge branch 'device-control-manage' into device-control-combined
szwarckonrad Aug 7, 2025
b6ae545
Merge branch 'main' into device-control-combined
szwarckonrad Aug 8, 2025
29592c6
remove redundant comments
szwarckonrad Aug 8, 2025
11985a1
Merge branch 'main' into device-control-combined
szwarckonrad Aug 8, 2025
816783d
Add tests for Trusted Devices API client, transforms, form, and list …
szwarckonrad Aug 8, 2025
806deff
Merge branch 'device-control-combined' into device-control-artifacts
szwarckonrad Aug 8, 2025
0949a8f
Merge branch 'main' into device-control-combined
szwarckonrad Aug 11, 2025
29fb9bd
Merge branch 'device-control-combined' into device-control-artifacts
szwarckonrad Aug 11, 2025
ae74be9
Unit coverage
szwarckonrad Aug 11, 2025
1cf678a
Merge branch 'main' into device-control-artifacts
szwarckonrad Aug 11, 2025
41ab373
Merge branch 'main' into device-control-combined
szwarckonrad Aug 12, 2025
2991187
Merge branch 'device-control-combined' into device-control-artifacts
szwarckonrad Aug 12, 2025
45fe76d
Merge branch 'main' into device-control-combined
szwarckonrad Aug 13, 2025
3ba08ee
Merge branch 'main' into device-control-artifacts
szwarckonrad Aug 13, 2025
cb75a3f
Merge branch 'main' into device-control-combined
szwarckonrad Aug 14, 2025
fb2be05
Merge branch 'device-control-combined' into device-control-artifacts
szwarckonrad Aug 14, 2025
cb20ec1
CR comments
szwarckonrad Aug 14, 2025
57f5a1e
Add user selection tracking for OS types in TrustedDevicesForm
szwarckonrad Aug 14, 2025
08f8bfc
Merge branch 'main' into device-control-combined
szwarckonrad Aug 14, 2025
d75a630
Merge branch 'main' into device-control-artifacts
szwarckonrad Aug 14, 2025
a945c18
Merge branch 'main' into device-control-combined
szwarckonrad Aug 14, 2025
5562369
Merge branch 'main' into device-control-combined
szwarckonrad Aug 18, 2025
115aace
Merge branch 'device-control-combined' into device-control-artifacts
szwarckonrad Aug 18, 2025
bdedfca
Merge branch 'main' into device-control-combined
szwarckonrad Aug 18, 2025
f139fab
Merge branch 'device-control-combined' into device-control-artifacts
szwarckonrad Aug 18, 2025
f226a89
cr
szwarckonrad Aug 18, 2025
5fb8ded
Merge branch 'main' into device-control-combined
szwarckonrad Aug 18, 2025
d61c7c2
lint
szwarckonrad Aug 18, 2025
0d2dc30
Merge branch 'main' into device-control-combined
szwarckonrad Aug 18, 2025
b758c66
Merge branch 'main' into device-control-combined
szwarckonrad Aug 19, 2025
5138a55
Merge branch 'device-control-combined' into device-control-artifacts
szwarckonrad Aug 19, 2025
1c36e39
Add OS_OPTIONS_PLACEHOLDER translation for operating system selection
szwarckonrad Aug 19, 2025
df24319
Merge branch 'main' into device-control-combined
szwarckonrad Aug 19, 2025
8803f79
Merge branch 'device-control-combined' into device-control-artifacts
szwarckonrad Aug 19, 2025
f140dff
Merge branch 'main' into device-control-artifacts
szwarckonrad Aug 20, 2025
b0f045b
Merge branch 'main' into device-control-artifacts
szwarckonrad Aug 20, 2025
1fb57bd
Merge branch 'device-control-artifacts' of https://github.com/szwarck…
szwarckonrad Aug 20, 2025
682e875
clean up comments
szwarckonrad Aug 20, 2025
541ef01
Merge branch 'main' into device-control-artifacts
szwarckonrad Aug 20, 2025
52365d1
Merge branch 'main' into device-control-artifacts
szwarckonrad Aug 21, 2025
3477046
Remove unused interfaces and enums from trusted_devices.ts
szwarckonrad Aug 21, 2025
3472731
Merge branch 'main' into device-control-artifacts
szwarckonrad Aug 21, 2025
b0ced2d
Merge branch 'main' into device-control-artifacts
szwarckonrad Aug 21, 2025
268f15a
Change export of trusted_devices to type export in index.ts
szwarckonrad Aug 21, 2025
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,347 @@
/*
* 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 {
GetTrustedDevicesRequestSchema,
GetTrustedDevicesSummaryRequestSchema,
PostTrustedDeviceCreateRequestSchema,
PutTrustedDeviceUpdateRequestSchema,
} from './trusted_devices';
import { OperatingSystem, TrustedDeviceConditionEntryField } from '@kbn/securitysolution-utils';
import type {
TrustedDeviceConditionEntry,
PutTrustedDevicesRequestParams,
NewTrustedDevice,
} from '../types';

describe('When invoking Trusted Devices Schema', () => {
describe('for GET List', () => {
const getListQueryParams = (page: unknown = 1, perPage: unknown = 20) => ({
page,
per_page: perPage,
});
const query = GetTrustedDevicesRequestSchema.query;

describe('query param validation', () => {
it('should return query params if valid', () => {
expect(query.validate(getListQueryParams())).toEqual({
page: 1,
per_page: 20,
});
});

it('should use default values', () => {
expect(query.validate(getListQueryParams(undefined, undefined))).toEqual({
page: 1,
per_page: 20,
});
expect(query.validate(getListQueryParams(undefined, 100))).toEqual({
page: 1,
per_page: 100,
});
expect(query.validate(getListQueryParams(10, undefined))).toEqual({
page: 10,
per_page: 20,
});
});

it('should throw if `page` param is not a number', () => {
expect(() => {
query.validate(getListQueryParams('one'));
}).toThrowError();
});

it('should throw if `page` param is less than 1', () => {
expect(() => {
query.validate(getListQueryParams(0));
}).toThrowError();
expect(() => {
query.validate(getListQueryParams(-1));
}).toThrowError();
});

it('should throw if `per_page` param is not a number', () => {
expect(() => {
query.validate(getListQueryParams(1, 'twenty'));
}).toThrowError();
});

it('should throw if `per_page` param is less than 1', () => {
expect(() => {
query.validate(getListQueryParams(1, 0));
}).toThrowError();
expect(() => {
query.validate(getListQueryParams(1, -1));
}).toThrowError();
});
});
});

describe('for GET Summary', () => {
const getListQueryParams = (kuery?: string) => ({ kuery });
const query = GetTrustedDevicesSummaryRequestSchema.query;

describe('query param validation', () => {
it('should return query params if valid without kuery', () => {
expect(query.validate(getListQueryParams())).toEqual({});
});

it('should return query params if valid with kuery', () => {
const kuery = `exception-list-agnostic.attributes.tags:"policy:caf1a334-53f3-4be9-814d-a32245f43d34" OR exception-list-agnostic.attributes.tags:"policy:all"`;
expect(query.validate(getListQueryParams(kuery))).toEqual({ kuery });
});
});
});

describe('for POST Create', () => {
const createConditionEntry = <T>(data?: T): TrustedDeviceConditionEntry => ({
field: TrustedDeviceConditionEntryField.HOST,
type: 'match',
operator: 'included',
value: 'DESKTOP-TEST-PC',
...(data || {}),
});
const createNewTrustedDevice = <T>(data?: T): NewTrustedDevice =>
({
name: 'Test Device',
description: 'this device is trusted',
os: OperatingSystem.WINDOWS,
effectScope: { type: 'global' },
entries: [createConditionEntry()],
...(data || {}),
} as NewTrustedDevice);
const body = PostTrustedDeviceCreateRequestSchema.body;

it('should not error on a valid message', () => {
const bodyMsg = createNewTrustedDevice();
expect(body.validate(bodyMsg)).toStrictEqual(bodyMsg);
});

it('should validate `name` is required', () => {
expect(() => body.validate(createNewTrustedDevice({ name: undefined }))).toThrow();
});

it('should validate `name` value to be non-empty', () => {
expect(() => body.validate(createNewTrustedDevice({ name: '' }))).toThrow();
});

it('should validate `description` as optional', () => {
const { description, ...bodyMsg } = createNewTrustedDevice();
expect(body.validate(bodyMsg)).toStrictEqual(bodyMsg);
});

it('should validate `os` to only accept known values', () => {
const bodyMsg = createNewTrustedDevice({ os: undefined });
expect(() => body.validate(bodyMsg)).toThrow();

expect(() => body.validate({ ...bodyMsg, os: '' })).toThrow();

expect(() => body.validate({ ...bodyMsg, os: 'winz' })).toThrow();

// Only Windows and macOS are supported (no Linux)
[OperatingSystem.MAC, OperatingSystem.WINDOWS].forEach((os) => {
expect(() => body.validate({ ...bodyMsg, os })).not.toThrow();
});

// Linux should NOT be supported
expect(() => body.validate({ ...bodyMsg, os: OperatingSystem.LINUX })).toThrow();
});

it('should validate `entries` as required', () => {
expect(() => body.validate(createNewTrustedDevice({ entries: undefined }))).toThrow();

const { entries, ...bodyMsg2 } = createNewTrustedDevice();
expect(() => body.validate(bodyMsg2)).toThrow();
});

it('should validate `entries` to have at least 1 item', () => {
expect(() => body.validate(createNewTrustedDevice({ entries: [] }))).toThrow();
});

describe('when `entries` are defined', () => {
it('should validate `entry.field` is required', () => {
const { field, ...entry } = createConditionEntry();
expect(() => body.validate(createNewTrustedDevice({ entries: [entry] }))).toThrow();
});

it('should validate `entry.field` does not accept empty values', () => {
const bodyMsg = createNewTrustedDevice({
entries: [createConditionEntry({ field: '' })],
});
expect(() => body.validate(bodyMsg)).toThrow();
});

it('should validate `entry.field` does not accept unknown values', () => {
const bodyMsg = createNewTrustedDevice({
entries: [createConditionEntry({ field: 'invalid_field' })],
});
expect(() => body.validate(bodyMsg)).toThrow();
});

it('should validate `entry.field` accepts all trusted device field names', () => {
[
TrustedDeviceConditionEntryField.USERNAME,
TrustedDeviceConditionEntryField.HOST,
TrustedDeviceConditionEntryField.DEVICE_ID,
TrustedDeviceConditionEntryField.MANUFACTURER,
TrustedDeviceConditionEntryField.PRODUCT_ID,
].forEach((field) => {
const bodyMsg = createNewTrustedDevice({
entries: [createConditionEntry({ field, value: 'test-value' })],
});

expect(() => body.validate(bodyMsg)).not.toThrow();
});
});

it('should validate `entry.type` does not accept unknown values', () => {
const bodyMsg = createNewTrustedDevice({
entries: [createConditionEntry({ type: 'invalid' })],
});
expect(() => body.validate(bodyMsg)).toThrow();
});

it('should validate `entry.type` accepts known values', () => {
['match', 'wildcard'].forEach((type) => {
const bodyMsg = createNewTrustedDevice({
entries: [createConditionEntry({ type })],
});
expect(() => body.validate(bodyMsg)).not.toThrow();
});
});

it('should validate `entry.operator` does not accept unknown values', () => {
const bodyMsg = createNewTrustedDevice({
entries: [createConditionEntry({ operator: 'invalid' })],
});
expect(() => body.validate(bodyMsg)).toThrow();
});

it('should validate `entry.operator` accepts known values', () => {
const bodyMsg = createNewTrustedDevice({
entries: [createConditionEntry({ operator: 'included' })],
});
expect(() => body.validate(bodyMsg)).not.toThrow();
});

it('should validate `entry.value` required', () => {
const { value, ...entry } = createConditionEntry();
expect(() => body.validate(createNewTrustedDevice({ entries: [entry] }))).toThrow();
});

it('should validate `entry.value` is non-empty', () => {
const bodyMsg = createNewTrustedDevice({ entries: [createConditionEntry({ value: '' })] });
expect(() => body.validate(bodyMsg)).toThrow();
});

it('should validate that duplicate fields are not allowed', () => {
const bodyMsg = createNewTrustedDevice({
entries: [
createConditionEntry({ field: TrustedDeviceConditionEntryField.HOST }),
createConditionEntry({ field: TrustedDeviceConditionEntryField.HOST }),
],
});
expect(() => body.validate(bodyMsg)).toThrow(/duplicatedEntry/);
});

it('should allow different fields in the same entry', () => {
const bodyMsg = createNewTrustedDevice({
entries: [
createConditionEntry({ field: TrustedDeviceConditionEntryField.HOST, value: 'HOST1' }),
createConditionEntry({
field: TrustedDeviceConditionEntryField.USERNAME,
value: 'user1',
}),
createConditionEntry({
field: TrustedDeviceConditionEntryField.DEVICE_ID,
value: 'device123',
}),
],
});
expect(() => body.validate(bodyMsg)).not.toThrow();
});
});

describe('effectScope validation', () => {
it('should validate global effect scope', () => {
const bodyMsg = createNewTrustedDevice({
effectScope: { type: 'global' },
});
expect(() => body.validate(bodyMsg)).not.toThrow();
});

it('should validate policy effect scope with policies array', () => {
const bodyMsg = createNewTrustedDevice({
effectScope: {
type: 'policy',
policies: ['policy-1', 'policy-2'],
},
});
expect(() => body.validate(bodyMsg)).not.toThrow();
});

it('should reject policy effect scope without policies array', () => {
const bodyMsg = createNewTrustedDevice({
effectScope: { type: 'policy' },
});
expect(() => body.validate(bodyMsg)).toThrow();
});
});
});

describe('for PUT Update', () => {
const createConditionEntry = <T>(data?: T): TrustedDeviceConditionEntry => ({
field: TrustedDeviceConditionEntryField.HOST,
type: 'match',
operator: 'included',
value: 'DESKTOP-TEST-PC',
...(data || {}),
});
const createNewTrustedDevice = <T>(data?: T): NewTrustedDevice =>
({
name: 'Test Device',
description: 'this device is trusted',
os: OperatingSystem.WINDOWS,
effectScope: { type: 'global' },
entries: [createConditionEntry()],
...(data || {}),
} as NewTrustedDevice);

const updateParams = <T>(data?: T): PutTrustedDevicesRequestParams => ({
id: 'validId',
...(data || {}),
});

const body = PutTrustedDeviceUpdateRequestSchema.body;
const params = PutTrustedDeviceUpdateRequestSchema.params;

it('should not error on a valid message', () => {
const bodyMsg = createNewTrustedDevice();
const paramsMsg = updateParams();
expect(body.validate(bodyMsg)).toStrictEqual(bodyMsg);
expect(params.validate(paramsMsg)).toStrictEqual(paramsMsg);
});

it('should validate `id` params is required', () => {
expect(() => params.validate(updateParams({ id: undefined }))).toThrow();
});

it('should validate `id` params to be string', () => {
expect(() => params.validate(updateParams({ id: 1 }))).toThrow();
});

it('should validate `version`', () => {
const bodyMsg = createNewTrustedDevice({ version: 'v1' });
expect(body.validate(bodyMsg)).toStrictEqual(bodyMsg);
});

it('should validate `version` must be string', () => {
const bodyMsg = createNewTrustedDevice({ version: 1 });
expect(() => body.validate(bodyMsg)).toThrow();
});
});
});
Loading
Loading