mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[EDR Workflows] Osquery Timeout (#169925)
https://github.com/elastic/security-team/issues/7775 This PR adds `Timeout` form field to all the places where Osquery query can be configured. Behind the scenes all the scenarios lead to the value being passed down to the fleet. Live Query  Live Pack Query  Saved Query  Osquery Response Action Query  --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
1b6822cb38
commit
e7cf51b63c
36 changed files with 389 additions and 71 deletions
|
@ -42,10 +42,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"metrics-data-source": {
|
||||
"dynamic": false,
|
||||
"properties": {}
|
||||
},
|
||||
"url": {
|
||||
"dynamic": false,
|
||||
"properties": {
|
||||
|
@ -1473,6 +1469,10 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"metrics-data-source": {
|
||||
"dynamic": false,
|
||||
"properties": {}
|
||||
},
|
||||
"canvas-element": {
|
||||
"dynamic": false,
|
||||
"properties": {
|
||||
|
@ -2168,6 +2168,9 @@
|
|||
"interval": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"timeout": {
|
||||
"type": "short"
|
||||
},
|
||||
"ecs_mapping": {
|
||||
"dynamic": false,
|
||||
"properties": {}
|
||||
|
@ -2216,6 +2219,9 @@
|
|||
"interval": {
|
||||
"type": "text"
|
||||
},
|
||||
"timeout": {
|
||||
"type": "short"
|
||||
},
|
||||
"platform": {
|
||||
"type": "keyword"
|
||||
},
|
||||
|
@ -2258,6 +2264,9 @@
|
|||
"interval": {
|
||||
"type": "text"
|
||||
},
|
||||
"timeout": {
|
||||
"type": "short"
|
||||
},
|
||||
"platform": {
|
||||
"type": "keyword"
|
||||
},
|
||||
|
@ -2679,50 +2688,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"apm-telemetry": {
|
||||
"dynamic": false,
|
||||
"properties": {}
|
||||
},
|
||||
"apm-server-schema": {
|
||||
"properties": {
|
||||
"schemaJson": {
|
||||
"type": "text",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"apm-service-group": {
|
||||
"properties": {
|
||||
"groupName": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"kuery": {
|
||||
"type": "text"
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"color": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"apm-custom-dashboards": {
|
||||
"properties": {
|
||||
"dashboardSavedObjectId": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"kuery": {
|
||||
"type": "text"
|
||||
},
|
||||
"serviceEnvironmentFilterEnabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"serviceNameFilterEnabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"enterprise_search_telemetry": {
|
||||
"dynamic": false,
|
||||
"properties": {}
|
||||
|
@ -3196,5 +3161,49 @@
|
|||
"index": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"apm-telemetry": {
|
||||
"dynamic": false,
|
||||
"properties": {}
|
||||
},
|
||||
"apm-server-schema": {
|
||||
"properties": {
|
||||
"schemaJson": {
|
||||
"type": "text",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"apm-service-group": {
|
||||
"properties": {
|
||||
"groupName": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"kuery": {
|
||||
"type": "text"
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"color": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"apm-custom-dashboards": {
|
||||
"properties": {
|
||||
"dashboardSavedObjectId": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"kuery": {
|
||||
"type": "text"
|
||||
},
|
||||
"serviceEnvironmentFilterEnabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"serviceNameFilterEnabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { inRangeRt } from '@kbn/io-ts-utils';
|
||||
|
||||
export const id = t.string;
|
||||
export type Id = t.TypeOf<typeof id>;
|
||||
|
@ -49,6 +50,11 @@ export type Interval = t.TypeOf<typeof interval>;
|
|||
export const intervalOrUndefined = t.union([interval, t.undefined]);
|
||||
export type IntervalOrUndefined = t.TypeOf<typeof intervalOrUndefined>;
|
||||
|
||||
export const timeout = inRangeRt(60, 60 * 15);
|
||||
export type Timeout = t.TypeOf<typeof timeout>;
|
||||
export const timeoutOrUndefined = t.union([timeout, t.undefined]);
|
||||
export type TimeoutOrUndefined = t.TypeOf<typeof timeoutOrUndefined>;
|
||||
|
||||
export const snapshot = t.boolean;
|
||||
export type Snapshot = t.TypeOf<typeof snapshot>;
|
||||
export const snapshotOrUndefined = t.union([snapshot, t.undefined]);
|
||||
|
|
|
@ -12,5 +12,8 @@
|
|||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
],
|
||||
"kbn_references": [
|
||||
"@kbn/io-ts-utils",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -125,9 +125,9 @@ describe('checking migration metadata changes on all registered SO types', () =>
|
|||
"monitoring-telemetry": "5d91bf75787d9d4dd2fae954d0b3f76d33d2e559",
|
||||
"observability-onboarding-state": "b16064c516aac64ae699c737d7d10b6e199bfded",
|
||||
"osquery-manager-usage-metric": "983bcbc3b7dda0aad29b20907db233abba709bcc",
|
||||
"osquery-pack": "6ab4358ca4304a12dcfc1777c8135b75cffb4397",
|
||||
"osquery-pack-asset": "b14101d3172c4b60eb5404696881ce5275c84152",
|
||||
"osquery-saved-query": "44f1161e165defe3f9b6ad643c68c542a765fcdb",
|
||||
"osquery-pack": "702e86b1a936153b39f65b0781bdc136e186e123",
|
||||
"osquery-pack-asset": "cd140bc2e4b092e93692b587bf6e38051ef94c75",
|
||||
"osquery-saved-query": "6095e288750aa3164dfe186c74bc5195c2bf2bd4",
|
||||
"policy-settings-protection-updates-note": "33924bb246f9e5bcb876109cc83e3c7a28308352",
|
||||
"query": "21cbbaa09abb679078145ce90087b1e88b7eae95",
|
||||
"risk-engine-configuration": "b105d4a3c6adce40708d729d12e5ef3c8fbd9508",
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
packIdOrUndefined,
|
||||
queryOrUndefined,
|
||||
arrayQueries,
|
||||
timeoutOrUndefined,
|
||||
} from '@kbn/osquery-io-ts-types';
|
||||
|
||||
export const createLiveQueryRequestBodySchema = t.partial({
|
||||
|
@ -23,6 +24,7 @@ export const createLiveQueryRequestBodySchema = t.partial({
|
|||
query: queryOrUndefined,
|
||||
queries: arrayQueries,
|
||||
saved_query_id: savedQueryIdOrUndefined,
|
||||
timeout: timeoutOrUndefined,
|
||||
ecs_mapping: ecsMappingOrUndefined,
|
||||
pack_id: packIdOrUndefined,
|
||||
alert_ids: t.array(t.string),
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
snapshotOrUndefined,
|
||||
removedOrUndefined,
|
||||
ecsMappingOrUndefined,
|
||||
timeoutOrUndefined,
|
||||
} from '@kbn/osquery-io-ts-types';
|
||||
|
||||
export const createSavedQueryRequestSchema = t.type({
|
||||
|
@ -27,6 +28,7 @@ export const createSavedQueryRequestSchema = t.type({
|
|||
query,
|
||||
version: versionOrUndefined,
|
||||
interval,
|
||||
timeout: timeoutOrUndefined,
|
||||
snapshot: snapshotOrUndefined,
|
||||
removed: removedOrUndefined,
|
||||
ecs_mapping: ecsMappingOrUndefined,
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
|
||||
import * as t from 'io-ts';
|
||||
import { toNumberRt } from '@kbn/io-ts-utils';
|
||||
import { timeoutOrUndefined } from '@kbn/osquery-io-ts-types';
|
||||
|
||||
export const updateSavedQueryRequestBodySchema = t.type({
|
||||
id: t.string,
|
||||
query: t.string,
|
||||
description: t.union([t.string, t.undefined]),
|
||||
interval: t.union([toNumberRt, t.undefined]),
|
||||
timeout: timeoutOrUndefined,
|
||||
snapshot: t.union([t.boolean, t.undefined]),
|
||||
removed: t.union([t.boolean, t.undefined]),
|
||||
platform: t.union([t.string, t.undefined]),
|
||||
|
|
|
@ -29,3 +29,8 @@ export const API_VERSIONS = {
|
|||
v1: '1',
|
||||
},
|
||||
};
|
||||
|
||||
export enum QUERY_TIMEOUT {
|
||||
DEFAULT = 60, // 60 seconds
|
||||
MAX = 60 * 15,
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import { navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
checkResults,
|
||||
fillInQueryTimeout,
|
||||
inputQuery,
|
||||
selectAllAgents,
|
||||
submitQuery,
|
||||
|
@ -36,13 +37,26 @@ describe('ALL - Live Query', { tags: ['@ess', '@serverless'] }, () => {
|
|||
cy.contains('Query is a required field').should('not.exist');
|
||||
checkResults();
|
||||
getAdvancedButton().click();
|
||||
fillInQueryTimeout('91');
|
||||
submitQuery();
|
||||
cy.contains('Timeout value must be lower than 900 seconds.');
|
||||
fillInQueryTimeout('89');
|
||||
submitQuery();
|
||||
cy.contains('Timeout value must be lower than 900 seconds.').should('not.exist');
|
||||
typeInOsqueryFieldInput('days{downArrow}{enter}');
|
||||
submitQuery();
|
||||
cy.contains('ECS field is required.');
|
||||
typeInECSFieldInput('message{downArrow}{enter}');
|
||||
|
||||
cy.intercept('POST', '/api/osquery/live_queries').as('postQuery');
|
||||
submitQuery();
|
||||
cy.contains('ECS field is required.').should('not.exist');
|
||||
|
||||
cy.wait('@postQuery').then((interception) => {
|
||||
expect(interception.request.body).to.have.property('query', 'select * from uptime;');
|
||||
expect(interception.request.body).to.have.property('timeout', 890);
|
||||
expect(interception.response?.statusCode).to.eq(200);
|
||||
expect(interception.response?.body.data.queries[0]).to.have.property('timeout', 890);
|
||||
});
|
||||
checkResults();
|
||||
cy.get('[data-gridcell-column-index="0"][data-gridcell-row-index="0"]').should('exist').click();
|
||||
cy.url().should('include', 'app/fleet/agents/');
|
||||
|
|
|
@ -29,18 +29,21 @@ describe('ALL - Live Query Packs', { tags: ['@ess', '@serverless'] }, () => {
|
|||
system_memory_linux_elastic: {
|
||||
ecs_mapping: {},
|
||||
interval: 3600,
|
||||
timeout: 700,
|
||||
platform: 'linux',
|
||||
query: 'SELECT * FROM memory_info;',
|
||||
},
|
||||
system_info_elastic: {
|
||||
ecs_mapping: {},
|
||||
interval: 3600,
|
||||
timeout: 200,
|
||||
platform: 'linux,windows,darwin',
|
||||
query: 'SELECT * FROM system_info;',
|
||||
},
|
||||
failingQuery: {
|
||||
ecs_mapping: {},
|
||||
interval: 10,
|
||||
timeout: 90,
|
||||
query: 'select opera_extensions.* from users join opera_extensions using (uid);',
|
||||
},
|
||||
},
|
||||
|
|
|
@ -197,18 +197,21 @@ describe('Packs - Create and Edit', { tags: ['@ess', '@serverless'] }, () => {
|
|||
const queries = {
|
||||
Query1: {
|
||||
interval: 3600,
|
||||
timeout: 60,
|
||||
query: 'select * from uptime;',
|
||||
removed: true,
|
||||
snapshot: false,
|
||||
},
|
||||
Query2: {
|
||||
interval: 3600,
|
||||
timeout: 60,
|
||||
query: 'select * from uptime;',
|
||||
removed: false,
|
||||
snapshot: false,
|
||||
},
|
||||
Query3: {
|
||||
interval: 3600,
|
||||
timeout: 60,
|
||||
query: 'select * from uptime;',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -40,6 +40,12 @@ export const submitQuery = () => {
|
|||
cy.contains('Submit').click();
|
||||
};
|
||||
|
||||
export const fillInQueryTimeout = (timeout: string) => {
|
||||
cy.getBySel('advanced-accordion-content').within(() => {
|
||||
cy.getBySel('timeout-input').clear().type(timeout);
|
||||
});
|
||||
};
|
||||
|
||||
// sometimes the results get stuck in the tests, this is a workaround
|
||||
export const checkResults = () => {
|
||||
cy.getBySel('osqueryResultsTable').then(($table) => {
|
||||
|
|
|
@ -10,3 +10,4 @@ export { QueryDescriptionField } from './query_description_field';
|
|||
export { IntervalField } from './interval_field';
|
||||
export { QueryIdField } from './query_id_field';
|
||||
export { ResultsTypeField } from './results_type_field';
|
||||
export { TimeoutField } from './timeout_field';
|
||||
|
|
114
x-pack/plugins/osquery/public/form/timeout_field.tsx
Normal file
114
x-pack/plugins/osquery/public/form/timeout_field.tsx
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* 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 React, { useCallback, useMemo } from 'react';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
import { useController } from 'react-hook-form';
|
||||
import type { EuiFieldNumberProps } from '@elastic/eui';
|
||||
import {
|
||||
EuiFieldNumber,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
EuiIconTip,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
||||
import { QUERY_TIMEOUT } from '../../common/constants';
|
||||
|
||||
const timeoutFieldValidations = {
|
||||
min: {
|
||||
message: i18n.translate('xpack.osquery.pack.queryFlyoutForm.timeoutFieldMinNumberError', {
|
||||
defaultMessage: 'Timeout value must be greater than {than} seconds.',
|
||||
values: { than: QUERY_TIMEOUT.DEFAULT },
|
||||
}),
|
||||
value: QUERY_TIMEOUT.DEFAULT,
|
||||
},
|
||||
max: {
|
||||
message: i18n.translate('xpack.osquery.pack.queryFlyoutForm.timeoutFieldMaxNumberError', {
|
||||
defaultMessage: 'Timeout value must be lower than {than} seconds.',
|
||||
values: { than: QUERY_TIMEOUT.MAX },
|
||||
}),
|
||||
value: QUERY_TIMEOUT.MAX,
|
||||
},
|
||||
};
|
||||
|
||||
interface TimeoutFieldProps {
|
||||
euiFieldProps?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
const TimeoutFieldComponent = ({ euiFieldProps }: TimeoutFieldProps) => {
|
||||
const {
|
||||
field: { onChange, value },
|
||||
fieldState: { error },
|
||||
} = useController({
|
||||
name: 'timeout',
|
||||
defaultValue: QUERY_TIMEOUT.DEFAULT,
|
||||
rules: {
|
||||
...timeoutFieldValidations,
|
||||
},
|
||||
});
|
||||
const handleChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const numberValue = e.target.valueAsNumber ? e.target.valueAsNumber : 0;
|
||||
onChange(numberValue);
|
||||
},
|
||||
[onChange]
|
||||
);
|
||||
const hasError = useMemo(() => !!error?.message, [error?.message]);
|
||||
|
||||
return (
|
||||
<EuiFormRow
|
||||
label={
|
||||
<EuiFlexGroup gutterSize="xs" alignItems="flexEnd">
|
||||
<EuiFlexItem grow={false}>
|
||||
<FormattedMessage id="xpack.osquery.liveQuery.timeout" defaultMessage="Timeout" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiIconTip
|
||||
content={i18n.translate('xpack.osquery.liveQuery.timeoutHint', {
|
||||
defaultMessage: 'Maximum time to wait for query results, default is 60 seconds.',
|
||||
})}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
}
|
||||
fullWidth
|
||||
error={error?.message}
|
||||
isInvalid={hasError}
|
||||
labelAppend={
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText size="xs" color="subdued">
|
||||
<FormattedMessage
|
||||
id="xpack.osquery.osquery.liveQuery.timeoutFieldOptionalLabel"
|
||||
defaultMessage="(optional)"
|
||||
/>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
}
|
||||
>
|
||||
<EuiFieldNumber
|
||||
isInvalid={hasError}
|
||||
value={value as EuiFieldNumberProps['value']}
|
||||
onChange={handleChange}
|
||||
fullWidth
|
||||
type="number"
|
||||
data-test-subj="timeout-input"
|
||||
name="timeout"
|
||||
min={QUERY_TIMEOUT.DEFAULT}
|
||||
max={QUERY_TIMEOUT.MAX}
|
||||
defaultValue={QUERY_TIMEOUT.DEFAULT}
|
||||
step={1}
|
||||
append="seconds"
|
||||
{...euiFieldProps}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
);
|
||||
};
|
||||
|
||||
export const TimeoutField = React.memo(TimeoutFieldComponent, deepEqual);
|
|
@ -10,7 +10,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import type { ECSMapping } from '@kbn/osquery-io-ts-types';
|
||||
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import { useForm as useHookForm, FormProvider } from 'react-hook-form';
|
||||
import { isEmpty, find, pickBy } from 'lodash';
|
||||
import { isEmpty, find, pickBy, isNumber } from 'lodash';
|
||||
|
||||
import {
|
||||
containsDynamicQuery,
|
||||
|
@ -39,6 +39,7 @@ export interface LiveQueryFormFields {
|
|||
savedQueryId?: string | null;
|
||||
ecs_mapping: ECSMapping;
|
||||
packId: string[];
|
||||
timeout?: number;
|
||||
queryType: 'query' | 'pack';
|
||||
}
|
||||
|
||||
|
@ -151,10 +152,10 @@ const LiveQueryFormComponent: React.FC<LiveQueryFormProps> = ({
|
|||
alert_ids: values.alertIds,
|
||||
pack_id: queryType === 'pack' && values?.packId?.length ? values?.packId[0] : undefined,
|
||||
ecs_mapping: values.ecs_mapping,
|
||||
timeout: values.timeout,
|
||||
},
|
||||
(value) => !isEmpty(value)
|
||||
(value) => !isEmpty(value) || isNumber(value)
|
||||
) as unknown as LiveQueryFormFields;
|
||||
|
||||
await mutateAsync(serializedData);
|
||||
},
|
||||
[alertAttachmentContext, mutateAsync, queryType]
|
||||
|
|
|
@ -11,6 +11,8 @@ import { EuiCodeBlock, EuiFormRow, EuiAccordion, EuiSpacer } from '@elastic/eui'
|
|||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { useController, useFormContext } from 'react-hook-form';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { QUERY_TIMEOUT } from '../../../common/constants';
|
||||
import { TimeoutField } from '../../form/timeout_field';
|
||||
import type { LiveQueryFormFields } from '.';
|
||||
import { OsqueryEditor } from '../../editor';
|
||||
import { useKibana } from '../../common/lib/kibana';
|
||||
|
@ -68,6 +70,7 @@ const LiveQueryQueryFieldComponent: React.FC<LiveQueryQueryFieldProps> = ({
|
|||
resetField('query', { defaultValue: savedQuery.query });
|
||||
resetField('savedQueryId', { defaultValue: savedQuery.savedQueryId });
|
||||
resetField('ecs_mapping', { defaultValue: savedQuery.ecs_mapping ?? {} });
|
||||
resetField('timeout', { defaultValue: savedQuery.timeout ?? QUERY_TIMEOUT.DEFAULT });
|
||||
|
||||
if (!isEmpty(savedQuery.ecs_mapping)) {
|
||||
setAdvancedContentState('open');
|
||||
|
@ -122,6 +125,7 @@ const LiveQueryQueryFieldComponent: React.FC<LiveQueryQueryFieldProps> = ({
|
|||
{!isSavedQueryDisabled && (
|
||||
<SavedQueriesDropdown disabled={isSavedQueryDisabled} onChange={handleSavedQueryChange} />
|
||||
)}
|
||||
|
||||
<EuiFormRow
|
||||
isInvalid={!!error?.message}
|
||||
error={error?.message}
|
||||
|
@ -155,6 +159,8 @@ const LiveQueryQueryFieldComponent: React.FC<LiveQueryQueryFieldProps> = ({
|
|||
data-test-subj="advanced-accordion-content"
|
||||
>
|
||||
<EuiSpacer size="xs" />
|
||||
<TimeoutField />
|
||||
<EuiSpacer size="s" />
|
||||
<ECSMappingEditorField euiFieldProps={ecsFieldProps} />
|
||||
</EuiAccordion>
|
||||
)}
|
||||
|
|
|
@ -14,6 +14,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import deepEqual from 'fast-deep-equal';
|
||||
import { useController, useFormContext, useWatch, useFieldArray } from 'react-hook-form';
|
||||
|
||||
import { QUERY_TIMEOUT } from '../../../common/constants';
|
||||
import { PackQueriesTable } from '../pack_queries_table';
|
||||
import { QueryFlyout } from '../queries/query_flyout';
|
||||
import { OsqueryPackUploader } from './pack_uploader';
|
||||
|
@ -84,6 +85,7 @@ const QueriesFieldComponent: React.FC<QueriesFieldProps> = ({ euiFieldProps }) =
|
|||
draft.id = updatedQuery.id;
|
||||
draft.interval = updatedQuery.interval;
|
||||
draft.query = updatedQuery.query;
|
||||
draft.timeout = updatedQuery.timeout;
|
||||
|
||||
if (updatedQuery.platform?.length) {
|
||||
draft.platform = updatedQuery.platform;
|
||||
|
@ -137,6 +139,7 @@ const QueriesFieldComponent: React.FC<QueriesFieldProps> = ({ euiFieldProps }) =
|
|||
{
|
||||
id: newQueryId,
|
||||
interval: newQuery.interval ?? parsedContent.interval ?? '3600',
|
||||
timeout: newQuery.timeout ?? parsedContent.timeout ?? QUERY_TIMEOUT.DEFAULT,
|
||||
query: newQuery.query,
|
||||
version: newQuery.version ?? parsedContent.version,
|
||||
snapshot: newQuery.snapshot ?? parsedContent.snapshot,
|
||||
|
|
|
@ -17,6 +17,7 @@ export const convertPackQueriesToSO = (queries: Record<string, Omit<PackQueryFor
|
|||
...pick(value, [
|
||||
'query',
|
||||
'interval',
|
||||
'timeout',
|
||||
'snapshot',
|
||||
'removed',
|
||||
'platform',
|
||||
|
|
|
@ -22,8 +22,14 @@ import { i18n } from '@kbn/i18n';
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { FormProvider } from 'react-hook-form';
|
||||
|
||||
import { DEFAULT_PLATFORM } from '../../../common/constants';
|
||||
import { QueryIdField, IntervalField, VersionField, ResultsTypeField } from '../../form';
|
||||
import { DEFAULT_PLATFORM, QUERY_TIMEOUT } from '../../../common/constants';
|
||||
import {
|
||||
QueryIdField,
|
||||
IntervalField,
|
||||
VersionField,
|
||||
ResultsTypeField,
|
||||
TimeoutField,
|
||||
} from '../../form';
|
||||
import { CodeEditorField } from '../../saved_queries/form/code_editor_field';
|
||||
import { PlatformCheckBoxGroupField } from './platform_checkbox_group_field';
|
||||
import { ALL_OSQUERY_VERSIONS_OPTIONS } from './constants';
|
||||
|
@ -79,6 +85,9 @@ const QueryFlyoutComponent: React.FC<QueryFlyoutProps> = ({
|
|||
});
|
||||
resetField('version', { defaultValue: savedQuery.version ? [savedQuery.version] : [] });
|
||||
resetField('interval', { defaultValue: savedQuery.interval ? savedQuery.interval : 3600 });
|
||||
resetField('timeout', {
|
||||
defaultValue: savedQuery.timeout ? savedQuery.timeout : QUERY_TIMEOUT.DEFAULT,
|
||||
});
|
||||
resetField('snapshot', { defaultValue: savedQuery.snapshot ?? true });
|
||||
resetField('removed', { defaultValue: savedQuery.removed });
|
||||
resetField('ecs_mapping', { defaultValue: savedQuery.ecs_mapping ?? {} });
|
||||
|
@ -146,9 +155,14 @@ const QueryFlyoutComponent: React.FC<QueryFlyoutProps> = ({
|
|||
<EuiSpacer />
|
||||
<ResultsTypeField />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<PlatformCheckBoxGroupField />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexGroup direction={'column'} justifyContent={'spaceBetween'}>
|
||||
<EuiFlexItem>
|
||||
<PlatformCheckBoxGroupField />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={0}>
|
||||
<TimeoutField />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer />
|
||||
<EuiFlexGroup>
|
||||
|
|
|
@ -11,6 +11,7 @@ import type { Draft } from 'immer';
|
|||
import { produce } from 'immer';
|
||||
import { useMemo } from 'react';
|
||||
import type { ECSMapping } from '@kbn/osquery-io-ts-types';
|
||||
import { QUERY_TIMEOUT } from '../../../common/constants';
|
||||
import type { Shard } from '../../../common/utils/converters';
|
||||
|
||||
export interface UsePackQueryFormProps {
|
||||
|
@ -22,6 +23,7 @@ export interface PackSOQueryFormData {
|
|||
id: string;
|
||||
query: string;
|
||||
interval: string;
|
||||
timeout?: number;
|
||||
snapshot?: boolean;
|
||||
removed?: boolean;
|
||||
platform?: string | undefined;
|
||||
|
@ -37,6 +39,7 @@ export interface PackQueryFormData {
|
|||
description?: string;
|
||||
query: string;
|
||||
interval: number;
|
||||
timeout?: number;
|
||||
snapshot?: boolean;
|
||||
removed?: boolean;
|
||||
platform?: string | undefined;
|
||||
|
@ -48,6 +51,7 @@ const deserializer = (payload: PackSOQueryFormData): PackQueryFormData => ({
|
|||
id: payload.id,
|
||||
query: payload.query,
|
||||
interval: payload.interval ? parseInt(payload.interval, 10) : 3600,
|
||||
timeout: payload.timeout || QUERY_TIMEOUT.DEFAULT,
|
||||
snapshot: payload.snapshot,
|
||||
removed: payload.removed,
|
||||
platform: payload.platform,
|
||||
|
|
|
@ -34,6 +34,7 @@ export interface SavedQuerySO {
|
|||
saved_object_id: string;
|
||||
description?: string;
|
||||
query: string;
|
||||
timeout?: number;
|
||||
ecs_mapping: ECSMapping;
|
||||
updated_at: string;
|
||||
prebuilt?: boolean;
|
||||
|
|
|
@ -23,6 +23,7 @@ import {
|
|||
QueryDescriptionField,
|
||||
VersionField,
|
||||
ResultsTypeField,
|
||||
TimeoutField,
|
||||
} from '../../form';
|
||||
import { PlatformCheckBoxGroupField } from '../../packs/queries/platform_checkbox_group_field';
|
||||
import { ALL_OSQUERY_VERSIONS_OPTIONS } from '../../packs/queries/constants';
|
||||
|
@ -89,12 +90,20 @@ const SavedQueryFormComponent: React.FC<SavedQueryFormProps> = ({
|
|||
<QueryDescriptionField euiFieldProps={euiFieldProps} />
|
||||
<EuiSpacer />
|
||||
<CodeEditorField euiFieldProps={euiFieldProps} />
|
||||
<EuiSpacer size="m" />
|
||||
<EuiFlexGroup justifyContent={'spaceBetween'}>
|
||||
<EuiFlexItem>
|
||||
<TimeoutField />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem />
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer size="xl" />
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem css={overflowCss}>
|
||||
<ECSMappingEditorField euiFieldProps={euiFieldProps} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
{!viewMode && hasPlayground && (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow={false}>
|
||||
|
|
|
@ -11,6 +11,7 @@ import type { Draft } from 'immer';
|
|||
import produce from 'immer';
|
||||
import { useMemo } from 'react';
|
||||
import type { ECSMapping } from '@kbn/osquery-io-ts-types';
|
||||
import { QUERY_TIMEOUT } from '../../../common/constants';
|
||||
import { useSavedQueries } from '../use_saved_queries';
|
||||
|
||||
export interface SavedQuerySOFormData {
|
||||
|
@ -18,6 +19,7 @@ export interface SavedQuerySOFormData {
|
|||
description?: string;
|
||||
query?: string;
|
||||
interval?: string;
|
||||
timeout?: number;
|
||||
snapshot?: boolean;
|
||||
removed?: boolean;
|
||||
platform?: string;
|
||||
|
@ -30,6 +32,7 @@ export interface SavedQueryFormData {
|
|||
description?: string;
|
||||
query?: string;
|
||||
interval?: number;
|
||||
timeout?: number;
|
||||
snapshot?: boolean;
|
||||
removed?: boolean;
|
||||
platform?: string;
|
||||
|
@ -46,6 +49,7 @@ const deserializer = (payload: SavedQuerySOFormData): SavedQueryFormData => ({
|
|||
description: payload.description,
|
||||
query: payload.query,
|
||||
interval: payload.interval ? parseInt(payload.interval, 10) : 3600,
|
||||
timeout: payload.timeout ?? QUERY_TIMEOUT.DEFAULT,
|
||||
snapshot: payload.snapshot ?? true,
|
||||
removed: payload.removed ?? false,
|
||||
platform: payload.platform,
|
||||
|
@ -95,6 +99,7 @@ export const useSavedQueryForm = ({ defaultValue }: UseSavedQueryFormProps) => {
|
|||
id: '',
|
||||
query: '',
|
||||
interval: 3600,
|
||||
timeout: QUERY_TIMEOUT.DEFAULT,
|
||||
ecs_mapping: {},
|
||||
snapshot: true,
|
||||
},
|
||||
|
|
|
@ -25,7 +25,7 @@ export interface SavedQueriesDropdownProps {
|
|||
disabled?: boolean;
|
||||
onChange: (
|
||||
value:
|
||||
| (Pick<SavedQuerySO, 'id' | 'description' | 'query' | 'ecs_mapping'> & {
|
||||
| (Pick<SavedQuerySO, 'id' | 'description' | 'query' | 'ecs_mapping' | 'timeout'> & {
|
||||
savedQueryId: string;
|
||||
})
|
||||
| null
|
||||
|
|
|
@ -24,23 +24,27 @@ interface OsqueryResponseActionsValues {
|
|||
id?: string;
|
||||
ecsMapping?: ECSMapping;
|
||||
query?: string;
|
||||
timeout: number;
|
||||
packId?: string;
|
||||
queries?: Array<{
|
||||
id: string;
|
||||
ecs_mapping: ECSMapping;
|
||||
query: string;
|
||||
timeout?: number;
|
||||
}>;
|
||||
}
|
||||
|
||||
interface OsqueryResponseActionsParamsFormFields {
|
||||
savedQueryId: string | null;
|
||||
ecs_mapping: ECSMapping;
|
||||
timeout: number;
|
||||
query: string;
|
||||
packId?: string[];
|
||||
queries: Array<{
|
||||
id: string;
|
||||
ecs_mapping: ECSMapping;
|
||||
query: string;
|
||||
timeout?: number;
|
||||
}>;
|
||||
queryType: 'query' | 'pack';
|
||||
}
|
||||
|
@ -115,6 +119,7 @@ const OsqueryResponseActionParamsFormComponent = ({
|
|||
: {
|
||||
savedQueryId: formData.savedQueryId,
|
||||
query: formData.query,
|
||||
timeout: formData.timeout,
|
||||
ecsMapping: formData.ecs_mapping,
|
||||
}
|
||||
);
|
||||
|
|
|
@ -21,6 +21,7 @@ export interface PackSavedObject {
|
|||
name: string;
|
||||
query: string;
|
||||
interval: number;
|
||||
timeout?: number;
|
||||
snapshot?: boolean;
|
||||
removed?: boolean;
|
||||
ecs_mapping?: Record<string, unknown>;
|
||||
|
@ -41,6 +42,7 @@ export interface SavedQuerySavedObject {
|
|||
description: string | undefined;
|
||||
query: string;
|
||||
interval: number | string;
|
||||
timeout?: number;
|
||||
snapshot?: boolean;
|
||||
removed?: boolean;
|
||||
platform: string;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import moment from 'moment';
|
||||
import { filter, isEmpty, map, omit, pick, pickBy, some } from 'lodash';
|
||||
import { filter, isEmpty, isNumber, map, omit, pick, pickBy, some } from 'lodash';
|
||||
import type { SavedObjectsClientContract } from '@kbn/core/server';
|
||||
import type { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common';
|
||||
import type { CreateLiveQueryRequestBodySchema } from '../../../common/api';
|
||||
|
@ -17,7 +17,7 @@ import { parseAgentSelection } from '../../lib/parse_agent_groups';
|
|||
import { packSavedObjectType } from '../../../common/types';
|
||||
import type { OsqueryAppContext } from '../../lib/osquery_app_context_services';
|
||||
import { convertSOQueriesToPack } from '../../routes/pack/utils';
|
||||
import { ACTIONS_INDEX } from '../../../common/constants';
|
||||
import { ACTIONS_INDEX, QUERY_TIMEOUT } from '../../../common/constants';
|
||||
import { TELEMETRY_EBT_LIVE_QUERY_EVENT } from '../../lib/telemetry/constants';
|
||||
import type { PackSavedObject } from '../../common/types';
|
||||
import { CustomHttpRequestError } from '../../common/error';
|
||||
|
@ -100,9 +100,10 @@ export const createActionHandler = async (
|
|||
ecs_mapping: packQuery.ecs_mapping,
|
||||
version: packQuery.version,
|
||||
platform: packQuery.platform,
|
||||
timeout: packQuery.timeout,
|
||||
agents: selectedAgents,
|
||||
},
|
||||
(value) => !isEmpty(value)
|
||||
(value) => !isEmpty(value) || isNumber(value)
|
||||
);
|
||||
})
|
||||
: await createDynamicQueries({
|
||||
|
@ -125,6 +126,7 @@ export const createActionHandler = async (
|
|||
input_type: 'osquery',
|
||||
agents: query.agents,
|
||||
user_id: metadata?.currentUser,
|
||||
...(query.timeout !== QUERY_TIMEOUT.DEFAULT ? { timeout: query.timeout } : {}),
|
||||
data: pick(query, ['id', 'query', 'ecs_mapping', 'version', 'platform']),
|
||||
})
|
||||
)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { isEmpty, map, pickBy } from 'lodash';
|
||||
import { isEmpty, isNumber, map, pickBy } from 'lodash';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import type { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common';
|
||||
|
@ -43,7 +43,7 @@ export const createDynamicQueries = async ({
|
|||
alert_ids: params.alert_ids,
|
||||
agents,
|
||||
},
|
||||
(value) => !isEmpty(value) || value === true
|
||||
(value) => !isEmpty(value) || value === true || isNumber(value)
|
||||
);
|
||||
})
|
||||
: [
|
||||
|
@ -61,10 +61,11 @@ export const createDynamicQueries = async ({
|
|||
: undefined,
|
||||
ecs_mapping: params.ecs_mapping,
|
||||
alert_ids: params.alert_ids,
|
||||
timeout: params.timeout,
|
||||
agents,
|
||||
...(error ? { error } : {}),
|
||||
},
|
||||
(value) => !isEmpty(value)
|
||||
(value) => !isEmpty(value) || isNumber(value)
|
||||
),
|
||||
];
|
||||
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
import { produce } from 'immer';
|
||||
import type { SavedObjectsType } from '@kbn/core/server';
|
||||
import { SECURITY_SOLUTION_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server';
|
||||
import {
|
||||
packAssetSavedObjectModelVersion1,
|
||||
packSavedObjectModelVersion1,
|
||||
savedQueryModelVersion1,
|
||||
} from './saved_object_model_versions';
|
||||
import {
|
||||
savedQuerySavedObjectType,
|
||||
packSavedObjectType,
|
||||
|
@ -67,6 +72,9 @@ export const savedQuerySavedObjectMappings: SavedObjectsType['mappings'] = {
|
|||
interval: {
|
||||
type: 'keyword',
|
||||
},
|
||||
timeout: {
|
||||
type: 'short',
|
||||
},
|
||||
ecs_mapping: {
|
||||
dynamic: false,
|
||||
properties: {},
|
||||
|
@ -80,6 +88,9 @@ export const savedQueryType: SavedObjectsType = {
|
|||
hidden: false,
|
||||
namespaceType: 'multiple-isolated',
|
||||
mappings: savedQuerySavedObjectMappings,
|
||||
modelVersions: {
|
||||
1: savedQueryModelVersion1,
|
||||
},
|
||||
management: {
|
||||
importableAndExportable: true,
|
||||
getTitle: (savedObject) => savedObject.attributes.id,
|
||||
|
@ -145,6 +156,9 @@ export const packSavedObjectMappings: SavedObjectsType['mappings'] = {
|
|||
interval: {
|
||||
type: 'text',
|
||||
},
|
||||
timeout: {
|
||||
type: 'short',
|
||||
},
|
||||
platform: {
|
||||
type: 'keyword',
|
||||
},
|
||||
|
@ -166,6 +180,9 @@ export const packType: SavedObjectsType = {
|
|||
hidden: false,
|
||||
namespaceType: 'multiple-isolated',
|
||||
mappings: packSavedObjectMappings,
|
||||
modelVersions: {
|
||||
1: packSavedObjectModelVersion1,
|
||||
},
|
||||
management: {
|
||||
defaultSearchField: 'name',
|
||||
importableAndExportable: true,
|
||||
|
@ -219,6 +236,9 @@ export const packAssetSavedObjectMappings: SavedObjectsType['mappings'] = {
|
|||
interval: {
|
||||
type: 'text',
|
||||
},
|
||||
timeout: {
|
||||
type: 'short',
|
||||
},
|
||||
platform: {
|
||||
type: 'keyword',
|
||||
},
|
||||
|
@ -242,6 +262,9 @@ export const packAssetType: SavedObjectsType = {
|
|||
importableAndExportable: true,
|
||||
visibleInManagement: false,
|
||||
},
|
||||
modelVersions: {
|
||||
1: packAssetSavedObjectModelVersion1,
|
||||
},
|
||||
namespaceType: 'agnostic',
|
||||
mappings: packAssetSavedObjectMappings,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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 type { SavedObjectsModelVersion } from '@kbn/core-saved-objects-server';
|
||||
|
||||
export const savedQueryModelVersion1: SavedObjectsModelVersion = {
|
||||
changes: [
|
||||
{
|
||||
type: 'mappings_addition',
|
||||
addedMappings: {
|
||||
timeout: { type: 'short' },
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const packSavedObjectModelVersion1: SavedObjectsModelVersion = {
|
||||
changes: [
|
||||
{
|
||||
type: 'mappings_addition',
|
||||
addedMappings: {
|
||||
queries: {
|
||||
properties: {
|
||||
timeout: { type: 'short' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const packAssetSavedObjectModelVersion1: SavedObjectsModelVersion = {
|
||||
changes: [
|
||||
{
|
||||
type: 'mappings_addition',
|
||||
addedMappings: {
|
||||
queries: {
|
||||
properties: {
|
||||
timeout: { type: 'short' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
|
@ -21,7 +21,16 @@ export const convertPackQueriesToSO = (queries) =>
|
|||
const ecsMapping = value.ecs_mapping && convertECSMappingToArray(value.ecs_mapping);
|
||||
acc.push({
|
||||
id: key,
|
||||
...pick(value, ['name', 'query', 'interval', 'platform', 'version', 'snapshot', 'removed']),
|
||||
...pick(value, [
|
||||
'name',
|
||||
'query',
|
||||
'interval',
|
||||
'platform',
|
||||
'version',
|
||||
'snapshot',
|
||||
'removed',
|
||||
'timeout',
|
||||
]),
|
||||
...(ecsMapping ? { ecs_mapping: ecsMapping } : {}),
|
||||
});
|
||||
|
||||
|
@ -32,6 +41,7 @@ export const convertPackQueriesToSO = (queries) =>
|
|||
name: string;
|
||||
query: string;
|
||||
interval: number;
|
||||
timeout?: number;
|
||||
snapshot?: boolean;
|
||||
removed?: boolean;
|
||||
ecs_mapping?: Record<string, unknown>;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { isEmpty, pickBy, some, isBoolean } from 'lodash';
|
||||
import { isEmpty, pickBy, some, isBoolean, isNumber } from 'lodash';
|
||||
import type { IRouter } from '@kbn/core/server';
|
||||
import type { CreateSavedQueryRequestSchemaDecoded } from '../../../common/api';
|
||||
import { API_VERSIONS } from '../../../common/constants';
|
||||
|
@ -50,6 +50,7 @@ export const createSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp
|
|||
interval,
|
||||
snapshot,
|
||||
removed,
|
||||
timeout,
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
ecs_mapping,
|
||||
} = request.body;
|
||||
|
@ -80,13 +81,14 @@ export const createSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp
|
|||
interval,
|
||||
snapshot,
|
||||
removed,
|
||||
timeout,
|
||||
ecs_mapping: convertECSMappingToArray(ecs_mapping),
|
||||
created_by: currentUser,
|
||||
created_at: new Date().toISOString(),
|
||||
updated_by: currentUser,
|
||||
updated_at: new Date().toISOString(),
|
||||
},
|
||||
(value) => !isEmpty(value) || isBoolean(value)
|
||||
(value) => !isEmpty(value) || isBoolean(value) || isNumber(value)
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -102,6 +104,7 @@ export const createSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp
|
|||
snapshot: attributes.snapshot,
|
||||
version: attributes.version,
|
||||
interval: attributes.interval,
|
||||
timeout: attributes.timeout,
|
||||
platform: attributes.platform,
|
||||
query: attributes.query,
|
||||
updated_at: attributes.updated_at,
|
||||
|
@ -109,7 +112,7 @@ export const createSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp
|
|||
saved_object_id: savedQuerySO.id,
|
||||
ecs_mapping,
|
||||
},
|
||||
(value) => !isEmpty(value)
|
||||
(value) => !isEmpty(value) || isNumber(value)
|
||||
);
|
||||
|
||||
return response.ok({
|
||||
|
|
|
@ -73,6 +73,7 @@ export const findSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC
|
|||
description,
|
||||
id,
|
||||
interval,
|
||||
timeout,
|
||||
platform,
|
||||
query,
|
||||
removed,
|
||||
|
@ -94,6 +95,7 @@ export const findSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC
|
|||
version,
|
||||
ecs_mapping: ecsMapping,
|
||||
interval,
|
||||
timeout,
|
||||
platform,
|
||||
query,
|
||||
updated_at: updatedAt,
|
||||
|
|
|
@ -64,6 +64,7 @@ export const readSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC
|
|||
description,
|
||||
id,
|
||||
interval,
|
||||
timeout,
|
||||
platform,
|
||||
query,
|
||||
removed,
|
||||
|
@ -85,6 +86,7 @@ export const readSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC
|
|||
version,
|
||||
ecs_mapping: ecsMapping,
|
||||
interval,
|
||||
timeout,
|
||||
platform,
|
||||
query,
|
||||
updated_at: updatedAt,
|
||||
|
|
|
@ -11,6 +11,7 @@ export interface SavedQueryResponse {
|
|||
description: string | undefined;
|
||||
query: string;
|
||||
interval: number | string;
|
||||
timeout?: number;
|
||||
snapshot?: boolean;
|
||||
removed?: boolean;
|
||||
platform?: string;
|
||||
|
@ -29,6 +30,7 @@ export interface UpdateSavedQueryResponse {
|
|||
description: string | undefined;
|
||||
query: string;
|
||||
interval: number | string;
|
||||
timeout?: number;
|
||||
snapshot?: boolean;
|
||||
removed?: boolean;
|
||||
platform?: string;
|
||||
|
|
|
@ -60,6 +60,7 @@ export const updateSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp
|
|||
query,
|
||||
version,
|
||||
interval,
|
||||
timeout,
|
||||
snapshot,
|
||||
removed,
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
|
@ -102,6 +103,7 @@ export const updateSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp
|
|||
query,
|
||||
version,
|
||||
interval,
|
||||
timeout,
|
||||
snapshot,
|
||||
removed,
|
||||
ecs_mapping: convertECSMappingToArray(ecs_mapping),
|
||||
|
@ -133,6 +135,7 @@ export const updateSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp
|
|||
version: attributes.version,
|
||||
ecs_mapping: attributes.ecs_mapping,
|
||||
interval: attributes.interval,
|
||||
timeout: attributes.timeout,
|
||||
platform: attributes.platform,
|
||||
query: attributes.query,
|
||||
updated_at: attributes.updated_at,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue