[8.3] [Osquery] Fix ECS editor field array value (#132786) (#134054)

* [Osquery] Fix ECS editor field array value (#132786)

(cherry picked from commit 272d9be670)

* revert
This commit is contained in:
Patryk Kopyciński 2022-06-09 19:57:02 +02:00 committed by GitHub
parent 8a40536c61
commit 0b6a03355b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 61 additions and 56 deletions

View file

@ -79,7 +79,7 @@ describe('ALL - Add Integration', () => {
it.skip('should have integration and packs copied when upgrading integration', () => {
const packageName = 'osquery_manager';
const oldVersion = '1.2.0';
const newVersion = '1.3.0';
const newVersion = '1.3.1';
cy.visit(`app/integrations/detail/${packageName}-${oldVersion}/overview`);
cy.contains('Add Osquery Manager').click();

View file

@ -17,7 +17,6 @@ import {
import { FormattedMessage } from '@kbn/i18n-react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useMutation } from 'react-query';
import deepMerge from 'deepmerge';
import styled from 'styled-components';
import { pickBy, isEmpty, map } from 'lodash';
@ -110,8 +109,12 @@ const LiveQueryFormComponent: React.FC<LiveQueryFormProps> = ({
options: {
stripEmptyFields: false,
},
serializer: ({
savedQueryId,
// eslint-disable-next-line @typescript-eslint/naming-convention
serializer: ({ savedQueryId, ecs_mapping, ...formData }) =>
ecs_mapping,
...formData
}) =>
pickBy(
{
...formData,
@ -120,20 +123,6 @@ const LiveQueryFormComponent: React.FC<LiveQueryFormProps> = ({
},
(value) => !isEmpty(value)
),
defaultValue: deepMerge(
{
agentSelection: {
agents: [],
allAgentsSelected: false,
platformsSelected: [],
policiesSelected: [],
},
query: '',
savedQueryId: null,
ecs_mapping: [],
},
defaultValue ?? {}
),
});
const { updateFieldValues, setFieldValue, submit, isSubmitting } = form;
@ -256,6 +245,7 @@ const LiveQueryFormComponent: React.FC<LiveQueryFormProps> = ({
/>
</>
)}
<UseField path="savedQueryId" component={GhostFormField} />
<UseField
path="query"
component={LiveQueryQueryField}
@ -385,7 +375,6 @@ const LiveQueryFormComponent: React.FC<LiveQueryFormProps> = ({
<EuiFlexItem>{queryFieldStepContent}</EuiFlexItem>
<EuiFlexItem>{resultsStepContent}</EuiFlexItem>
</EuiFlexGroup>
<UseField path="savedQueryId" component={GhostFormField} />
</Form>
{showSavedQueryFlyout ? (
<SavedQueryFlyout

View file

@ -28,6 +28,7 @@ export const liveQueryFormSchema = {
validations: [],
},
query: {
defaultValue: '',
type: FIELD_TYPES.TEXT,
validations: [
{

View file

@ -143,7 +143,7 @@ const QueriesFieldComponent: React.FC<QueriesFieldProps> = ({
pickBy(
{
id: newQueryId,
interval: newQuery.interval ?? parsedContent.interval,
interval: newQuery.interval ?? parsedContent.interval ?? '3600',
query: newQuery.query,
version: newQuery.version ?? parsedContent.version,
platform: getSupportedPlatforms(newQuery.platform ?? parsedContent.platform),

View file

@ -398,7 +398,7 @@ const OsqueryColumnFieldComponent: React.FC<OsqueryColumnFieldProps> = ({
return ecsKeySchemaOption?.value?.normalization !== 'array';
}
return true;
return !!ecsKey?.length;
}, [typeValue, formData, item.path]);
const onTypeChange = useCallback(
@ -637,6 +637,7 @@ export const ECSMappingEditorForm: React.FC<ECSMappingEditorFormProps> = ({
osquerySchemaOptions,
editForm: !isLastItem,
},
readDefaultValueOnForm: !item.isNew,
config: {
valueChangeDebounceTime: 300,
type: FIELD_TYPES.COMBO_BOX,
@ -702,6 +703,7 @@ export const ECSMappingEditorForm: React.FC<ECSMappingEditorFormProps> = ({
component={ECSComboboxField}
euiFieldProps={ecsComboBoxEuiFieldProps}
validationData={validationData}
readDefaultValueOnForm={!item.isNew}
// @ts-expect-error update types
config={config}
/>
@ -1017,7 +1019,9 @@ export const ECSMappingEditorField = React.memo(
if (itemKey) {
const serializedFormData = formDataSerializer();
const itemValue =
serializedFormData.ecs_mapping && serializedFormData.ecs_mapping[`${itemKey}`]?.field;
serializedFormData.ecs_mapping &&
(serializedFormData.ecs_mapping[`${itemKey}`]?.field ||
serializedFormData.ecs_mapping[`${itemKey}`]?.value);
if (itemValue && onAdd.current) {
onAdd.current();

View file

@ -6,7 +6,7 @@
*/
import { EuiIcon } from '@elastic/eui';
import React, { useEffect, useState } from 'react';
import React, { useMemo } from 'react';
import { getPlatformIconModule } from './helpers';
export interface PlatformIconProps {
@ -14,19 +14,9 @@ export interface PlatformIconProps {
}
const PlatformIconComponent: React.FC<PlatformIconProps> = ({ platform }) => {
const [Icon, setIcon] = useState<React.ReactElement | null>(null);
const platformIconModule = useMemo(() => getPlatformIconModule(platform), [platform]);
// FIXME: This is a hack to force the icon to be loaded asynchronously.
useEffect(() => {
const interval = setInterval(() => {
const platformIconModule = getPlatformIconModule(platform);
setIcon(<EuiIcon type={platformIconModule} title={platform} size="l" />);
}, 0);
return () => clearInterval(interval);
}, [platform, setIcon]);
return Icon;
return <EuiIcon type={platformIconModule} title={platform} size="l" />;
};
export const PlatformIcon = React.memo(PlatformIconComponent);

View file

@ -30,6 +30,7 @@ import { ALL_OSQUERY_VERSIONS_OPTIONS } from './constants';
import { UsePackQueryFormProps, PackFormData, usePackQueryForm } from './use_pack_query_form';
import { SavedQueriesDropdown } from '../../saved_queries/saved_queries_dropdown';
import { ECSMappingEditorField } from './lazy_ecs_mapping_editor_field';
import { useKibana } from '../../common/lib/kibana';
const CommonUseField = getUseField({ component: Field });
@ -46,6 +47,7 @@ const QueryFlyoutComponent: React.FC<QueryFlyoutProps> = ({
onSave,
onClose,
}) => {
const permissions = useKibana().services.application.capabilities.osquery;
const [isEditMode] = useState(!!defaultValue);
const { form } = usePackQueryForm({
uniqueQueryIds,
@ -117,7 +119,7 @@ const QueryFlyoutComponent: React.FC<QueryFlyoutProps> = ({
</EuiFlyoutHeader>
<EuiFlyoutBody>
<Form form={form}>
{!isEditMode ? (
{!isEditMode && permissions.readSavedQueries ? (
<>
<SavedQueriesDropdown onChange={handleSetQueryValue} />
<EuiSpacer />

View file

@ -14,7 +14,7 @@ import { FIELD_TYPES } from '../../shared_imports';
import {
createIdFieldValidations,
intervalFieldValidation,
intervalFieldValidations,
queryFieldValidation,
} from './validations';
@ -46,7 +46,7 @@ export const createFormSchema = (ids: Set<string>) => ({
label: i18n.translate('xpack.osquery.pack.queryFlyoutForm.intervalFieldLabel', {
defaultMessage: 'Interval (s)',
}),
validations: [{ validator: intervalFieldValidation }],
validations: intervalFieldValidations,
},
platform: {
type: FIELD_TYPES.TEXT,

View file

@ -7,7 +7,7 @@
import { i18n } from '@kbn/i18n';
import { ValidationFunc, fieldValidators } from '../../shared_imports';
import { ValidationConfig, ValidationFunc, fieldValidators } from '../../shared_imports';
export { queryFieldValidation } from '../../common/validations';
const idPattern = /^[a-zA-Z0-9-_]+$/;
@ -48,14 +48,30 @@ export const createIdFieldValidations = (ids: Set<string>) => [
createUniqueIdValidation(ids),
];
export const intervalFieldValidation: ValidationFunc<
export const intervalFieldValidations: Array<
ValidationConfig<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
any,
string,
number
> = fieldValidators.numberGreaterThanField({
>
> = [
{
validator: fieldValidators.numberGreaterThanField({
than: 0,
message: i18n.translate('xpack.osquery.pack.queryFlyoutForm.invalidIntervalField', {
message: i18n.translate('xpack.osquery.pack.queryFlyoutForm.intervalFieldMinNumberError', {
defaultMessage: 'A positive interval value is required',
}),
});
}),
},
{
validator: fieldValidators.numberSmallerThanField({
than: 604800,
message: ({ than }) =>
i18n.translate('xpack.osquery.pack.queryFlyoutForm.intervalFieldMaxNumberError', {
defaultMessage: 'An interval value must be lower than {than}',
values: { than },
}),
}),
},
];

View file

@ -12,6 +12,7 @@ export type {
FormData,
FormHook,
FormSchema,
ValidationConfig,
ValidationError,
ValidationFunc,
ValidationFuncArg,

View file

@ -19,14 +19,16 @@ const getInstallation = async (osqueryContext: OsqueryAppContext) =>
export const getInstalledSavedQueriesMap = async (osqueryContext: OsqueryAppContext) => {
const installation = await getInstallation(osqueryContext);
if (installation) {
return reduce(
return reduce<KibanaAssetReference, Record<string, KibanaAssetReference>>(
installation.installed_kibana,
// @ts-expect-error not sure why it shouts, but still it's properly typed
(acc: Record<string, KibanaAssetReference>, item: KibanaAssetReference) => {
(acc, item) => {
if (item.type === savedQuerySavedObjectType) {
return { ...acc, [item.id]: item };
}
return acc;
},
{}
);

View file

@ -21923,7 +21923,7 @@
"xpack.osquery.pack.queryFlyoutForm.idFieldLabel": "ID",
"xpack.osquery.pack.queryFlyoutForm.intervalFieldLabel": "Intervalle (s)",
"xpack.osquery.pack.queryFlyoutForm.invalidIdError": "Les caractères doivent être alphanumériques, _ ou -",
"xpack.osquery.pack.queryFlyoutForm.invalidIntervalField": "Une valeur d'intervalle positive est requise",
"xpack.osquery.pack.queryFlyoutForm.intervalFieldMinNumberError": "Une valeur d'intervalle positive est requise",
"xpack.osquery.pack.queryFlyoutForm.mappingEcsFieldLabel": "Champ ECS",
"xpack.osquery.pack.queryFlyoutForm.mappingValueFieldLabel": "Valeur",
"xpack.osquery.pack.queryFlyoutForm.osqueryResultFieldRequiredErrorMessage": "Valeur obligatoire.",

View file

@ -22061,7 +22061,7 @@
"xpack.osquery.pack.queryFlyoutForm.idFieldLabel": "ID",
"xpack.osquery.pack.queryFlyoutForm.intervalFieldLabel": "間隔",
"xpack.osquery.pack.queryFlyoutForm.invalidIdError": "文字は英数字、_、または-でなければなりません",
"xpack.osquery.pack.queryFlyoutForm.invalidIntervalField": "正の間隔値が必要です",
"xpack.osquery.pack.queryFlyoutForm.intervalFieldMinNumberError": "正の間隔値が必要です",
"xpack.osquery.pack.queryFlyoutForm.mappingEcsFieldLabel": "ECSフィールド",
"xpack.osquery.pack.queryFlyoutForm.mappingValueFieldLabel": "値",
"xpack.osquery.pack.queryFlyoutForm.osqueryResultFieldRequiredErrorMessage": "値が必要です。",

View file

@ -22092,7 +22092,7 @@
"xpack.osquery.pack.queryFlyoutForm.idFieldLabel": "ID",
"xpack.osquery.pack.queryFlyoutForm.intervalFieldLabel": "时间间隔 (s)",
"xpack.osquery.pack.queryFlyoutForm.invalidIdError": "字符必须是数字字母、_ 或 -",
"xpack.osquery.pack.queryFlyoutForm.invalidIntervalField": "时间间隔值必须为正数",
"xpack.osquery.pack.queryFlyoutForm.intervalFieldMinNumberError": "时间间隔值必须为正数",
"xpack.osquery.pack.queryFlyoutForm.mappingEcsFieldLabel": "ECS 字段",
"xpack.osquery.pack.queryFlyoutForm.mappingValueFieldLabel": "值",
"xpack.osquery.pack.queryFlyoutForm.osqueryResultFieldRequiredErrorMessage": "“值”必填。",