mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Osquery] Fix 7.16.0 BC1 issues (#116074)
This commit is contained in:
parent
645cecdf1f
commit
f6dd54a00a
30 changed files with 460 additions and 177 deletions
|
@ -330,7 +330,7 @@
|
|||
"react-moment-proptypes": "^1.7.0",
|
||||
"react-monaco-editor": "^0.41.2",
|
||||
"react-popper-tooltip": "^2.10.1",
|
||||
"react-query": "^3.27.0",
|
||||
"react-query": "^3.28.0",
|
||||
"react-redux": "^7.2.0",
|
||||
"react-resizable": "^1.7.5",
|
||||
"react-resize-detector": "^4.2.0",
|
||||
|
|
|
@ -28,13 +28,12 @@ const AgentsPolicyLinkComponent: React.FC<AgentsPolicyLinkProps> = ({ policyId }
|
|||
const {
|
||||
application: { getUrlForApp, navigateToApp },
|
||||
} = useKibana().services;
|
||||
|
||||
const { data } = useAgentPolicy({ policyId });
|
||||
|
||||
const href = useMemo(
|
||||
() =>
|
||||
getUrlForApp(PLUGIN_ID, {
|
||||
path: `#` + pagePathGetters.policy_details({ policyId })[1],
|
||||
path: pagePathGetters.policy_details({ policyId })[1],
|
||||
}),
|
||||
[getUrlForApp, policyId]
|
||||
);
|
||||
|
@ -45,7 +44,7 @@ const AgentsPolicyLinkComponent: React.FC<AgentsPolicyLinkProps> = ({ policyId }
|
|||
event.preventDefault();
|
||||
|
||||
return navigateToApp(PLUGIN_ID, {
|
||||
path: `#` + pagePathGetters.policy_details({ policyId })[1],
|
||||
path: pagePathGetters.policy_details({ policyId })[1],
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
|
@ -25,7 +25,7 @@ const AgentIdToNameComponent: React.FC<AgentIdToNameProps> = ({ agentId }) => {
|
|||
<EuiLink
|
||||
className="eui-textTruncate"
|
||||
href={getUrlForApp(PLUGIN_ID, {
|
||||
path: `#` + pagePathGetters.agent_details({ agentId })[1],
|
||||
path: pagePathGetters.agent_details({ agentId })[1],
|
||||
})}
|
||||
target="_blank"
|
||||
>
|
||||
|
|
|
@ -43,7 +43,7 @@ interface AgentsTableProps {
|
|||
}
|
||||
|
||||
const perPage = 10;
|
||||
const DEBOUNCE_DELAY = 100; // ms
|
||||
const DEBOUNCE_DELAY = 300; // ms
|
||||
|
||||
const AgentsTableComponent: React.FC<AgentsTableProps> = ({ agentSelection, onChange }) => {
|
||||
// search related
|
||||
|
|
|
@ -22,8 +22,8 @@ export const useAgentPolicies = (policyIds: string[] = []) => {
|
|||
queryFn: () => http.get(`/internal/osquery/fleet_wrapper/agent_policies/${policyId}`),
|
||||
enabled: policyIds.length > 0,
|
||||
onSuccess: () => setErrorToast(),
|
||||
onError: (error) =>
|
||||
setErrorToast(error as Error, {
|
||||
onError: (error: Error) =>
|
||||
setErrorToast(error, {
|
||||
title: i18n.translate('xpack.osquery.action_policy_details.fetchError', {
|
||||
defaultMessage: 'Error while fetching policy details',
|
||||
}),
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* 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 { EuiBetaBadge, EuiText } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const BetaBadgeRowWrapper = styled(EuiText)`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const Wrapper = styled.div`
|
||||
padding-left: ${({ theme }) => theme.eui.paddingSizes.s};
|
||||
`;
|
||||
|
||||
const betaBadgeLabel = i18n.translate('xpack.osquery.common.tabBetaBadgeLabel', {
|
||||
defaultMessage: 'Beta',
|
||||
});
|
||||
|
||||
const betaBadgeTooltipContent = i18n.translate('xpack.osquery.common.tabBetaBadgeTooltipContent', {
|
||||
defaultMessage:
|
||||
'This feature is under active development. Extra functionality is coming, and some functionality may change.',
|
||||
});
|
||||
|
||||
const BetaBadgeComponent = () => (
|
||||
<Wrapper>
|
||||
<EuiBetaBadge label={betaBadgeLabel} tooltipContent={betaBadgeTooltipContent} />
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
export const BetaBadge = React.memo(BetaBadgeComponent);
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* 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 { EuiLink, EuiFormRow, EuiFilePicker, EuiSpacer } from '@elastic/eui';
|
||||
import React, { useCallback, useState, useRef } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
const SUPPORTED_CONFIG_EXTENSIONS = ['application/json', 'text/plain'];
|
||||
|
||||
const ExampleConfigLink = React.memo(() => (
|
||||
<EuiLink
|
||||
href="https://github.com/osquery/osquery/blob/master/tools/deployment/osquery.example.conf"
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.osquery.configUploader.exampleConfigLinkLabel"
|
||||
defaultMessage="Example config"
|
||||
/>
|
||||
</EuiLink>
|
||||
));
|
||||
|
||||
ExampleConfigLink.displayName = 'ExampleOsqueryConfigLink';
|
||||
|
||||
interface ConfigUploaderProps {
|
||||
onChange: (payload: Record<string, unknown>) => void;
|
||||
}
|
||||
|
||||
const ConfigUploaderComponent: React.FC<ConfigUploaderProps> = ({ onChange }) => {
|
||||
const filePickerRef = useRef<EuiFilePicker>(null);
|
||||
const [isInvalid, setIsInvalid] = useState<string | null>(null);
|
||||
// @ts-expect-error update types
|
||||
let fileReader;
|
||||
|
||||
const handleFileRead = () => {
|
||||
// @ts-expect-error update types
|
||||
const content = fileReader.result;
|
||||
|
||||
let parsedContent;
|
||||
|
||||
try {
|
||||
parsedContent = JSON.parse(content.replaceAll('\\\n', ''), (key, value) => {
|
||||
if (key === 'query') {
|
||||
// remove any multiple spaces from the query
|
||||
return value.replaceAll(/\s(?=\s)/gm, '');
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
setIsInvalid(null);
|
||||
} catch (error) {
|
||||
setIsInvalid(error);
|
||||
// @ts-expect-error update types
|
||||
filePickerRef.current?.removeFiles(new Event('fake'));
|
||||
}
|
||||
|
||||
onChange(parsedContent);
|
||||
// @ts-expect-error update types
|
||||
filePickerRef.current?.removeFiles(new Event('fake'));
|
||||
};
|
||||
|
||||
// @ts-expect-error update types
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const handleFileChosen = (file) => {
|
||||
fileReader = new FileReader();
|
||||
fileReader.onloadend = handleFileRead;
|
||||
fileReader.readAsText(file);
|
||||
};
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
(inputFiles) => {
|
||||
if (!inputFiles.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
inputFiles.length &&
|
||||
((!!inputFiles[0].type.length &&
|
||||
!SUPPORTED_CONFIG_EXTENSIONS.includes(inputFiles[0].type)) ??
|
||||
!inputFiles[0].name.endsWith('.conf'))
|
||||
) {
|
||||
setIsInvalid(
|
||||
i18n.translate('xpack.osquery.configUploader.unsupportedFileTypeText', {
|
||||
defaultMessage:
|
||||
'File type {fileType} is not supported, please upload {supportedFileTypes} config file',
|
||||
values: {
|
||||
fileType: inputFiles[0].type,
|
||||
supportedFileTypes: SUPPORTED_CONFIG_EXTENSIONS.join(' or '),
|
||||
},
|
||||
})
|
||||
);
|
||||
// @ts-expect-error update types
|
||||
filePickerRef.current?.removeFiles(new Event('fake'));
|
||||
return;
|
||||
}
|
||||
|
||||
handleFileChosen(inputFiles[0]);
|
||||
},
|
||||
[handleFileChosen]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiSpacer size="xl" />
|
||||
<EuiFormRow
|
||||
fullWidth
|
||||
labelAppend={<ExampleConfigLink />}
|
||||
isInvalid={!!isInvalid}
|
||||
error={<>{`${isInvalid}`}</>}
|
||||
>
|
||||
<EuiFilePicker
|
||||
ref={filePickerRef}
|
||||
id="osquery_config_picker"
|
||||
initialPromptText={i18n.translate('xpack.osquery.configUploader.initialPromptTextLabel', {
|
||||
defaultMessage: 'Select or drag and drop osquery config file',
|
||||
})}
|
||||
onChange={handleInputChange}
|
||||
display="large"
|
||||
fullWidth
|
||||
isInvalid={!!isInvalid}
|
||||
accept={SUPPORTED_CONFIG_EXTENSIONS.join(',')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const ConfigUploader = React.memo(ConfigUploaderComponent);
|
|
@ -14,13 +14,11 @@ import { useKibana, isModifiedEvent, isLeftClickEvent } from '../common/lib/kiba
|
|||
|
||||
interface NavigationButtonsProps {
|
||||
isDisabled?: boolean;
|
||||
integrationPolicyId?: string | undefined;
|
||||
agentPolicyId?: string | undefined;
|
||||
}
|
||||
|
||||
const NavigationButtonsComponent: React.FC<NavigationButtonsProps> = ({
|
||||
isDisabled = false,
|
||||
integrationPolicyId,
|
||||
agentPolicyId,
|
||||
}) => {
|
||||
const {
|
||||
|
@ -52,7 +50,7 @@ const NavigationButtonsComponent: React.FC<NavigationButtonsProps> = ({
|
|||
);
|
||||
|
||||
const packsHref = getUrlForApp(PLUGIN_ID, {
|
||||
path: integrationPolicyId ? `/packs/${integrationPolicyId}/edit` : `/packs`,
|
||||
path: `/packs`,
|
||||
});
|
||||
|
||||
const packsClick = useCallback(
|
||||
|
@ -60,11 +58,11 @@ const NavigationButtonsComponent: React.FC<NavigationButtonsProps> = ({
|
|||
if (!isModifiedEvent(event) && isLeftClickEvent(event)) {
|
||||
event.preventDefault();
|
||||
navigateToApp(PLUGIN_ID, {
|
||||
path: integrationPolicyId ? `/packs/${integrationPolicyId}/edit` : `/packs`,
|
||||
path: `/packs`,
|
||||
});
|
||||
}
|
||||
},
|
||||
[navigateToApp, integrationPolicyId]
|
||||
[navigateToApp]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { get, isEmpty, unset, set } from 'lodash';
|
||||
import { pickBy, get, isEmpty, isString, unset, set, intersection } from 'lodash';
|
||||
import satisfies from 'semver/functions/satisfies';
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
|
@ -15,7 +15,7 @@ import {
|
|||
EuiLink,
|
||||
EuiAccordion,
|
||||
} from '@elastic/eui';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { produce } from 'immer';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import useDebounce from 'react-use/lib/useDebounce';
|
||||
|
@ -35,7 +35,105 @@ import {
|
|||
import { useKibana } from '../common/lib/kibana';
|
||||
import { NavigationButtons } from './navigation_buttons';
|
||||
import { DisabledCallout } from './disabled_callout';
|
||||
import { Form, useForm, Field, getUseField, FIELD_TYPES, fieldValidators } from '../shared_imports';
|
||||
import { ConfigUploader } from './config_uploader';
|
||||
import {
|
||||
Form,
|
||||
useForm,
|
||||
useFormData,
|
||||
Field,
|
||||
getUseField,
|
||||
FIELD_TYPES,
|
||||
fieldValidators,
|
||||
ValidationFunc,
|
||||
} from '../shared_imports';
|
||||
|
||||
// https://github.com/elastic/beats/blob/master/x-pack/osquerybeat/internal/osqd/args.go#L57
|
||||
const RESTRICTED_CONFIG_OPTIONS = [
|
||||
'force',
|
||||
'disable_watchdog',
|
||||
'utc',
|
||||
'events_expiry',
|
||||
'extensions_socket',
|
||||
'extensions_interval',
|
||||
'extensions_timeout',
|
||||
'pidfile',
|
||||
'database_path',
|
||||
'extensions_autoload',
|
||||
'flagfile',
|
||||
'config_plugin',
|
||||
'logger_plugin',
|
||||
'pack_delimiter',
|
||||
'config_refresh',
|
||||
];
|
||||
|
||||
export const configProtectedKeysValidator = (
|
||||
...args: Parameters<ValidationFunc>
|
||||
): ReturnType<ValidationFunc> => {
|
||||
const [{ value }] = args;
|
||||
|
||||
let configJSON;
|
||||
try {
|
||||
configJSON = JSON.parse(value as string);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
const restrictedFlags = intersection(
|
||||
Object.keys(configJSON?.options ?? {}),
|
||||
RESTRICTED_CONFIG_OPTIONS
|
||||
);
|
||||
|
||||
if (restrictedFlags.length) {
|
||||
return {
|
||||
code: 'ERR_RESTRICTED_OPTIONS',
|
||||
message: i18n.translate(
|
||||
'xpack.osquery.fleetIntegration.osqueryConfig.restrictedOptionsErrorMessage',
|
||||
{
|
||||
defaultMessage:
|
||||
'The following osquery options are not supported and must be removed: {restrictedFlags}.',
|
||||
values: {
|
||||
restrictedFlags: restrictedFlags.join(', '),
|
||||
},
|
||||
}
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
export const packConfigFilesValidator = (
|
||||
...args: Parameters<ValidationFunc>
|
||||
): ReturnType<ValidationFunc> => {
|
||||
const [{ value }] = args;
|
||||
|
||||
let configJSON;
|
||||
try {
|
||||
configJSON = JSON.parse(value as string);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
const packsWithConfigPaths = Object.keys(pickBy(configJSON?.packs ?? {}, isString));
|
||||
|
||||
if (packsWithConfigPaths.length) {
|
||||
return {
|
||||
code: 'ERR_RESTRICTED_OPTIONS',
|
||||
message: i18n.translate(
|
||||
'xpack.osquery.fleetIntegration.osqueryConfig.packConfigFilesErrorMessage',
|
||||
{
|
||||
defaultMessage:
|
||||
'Pack configuration files are not supported. These packs must be removed: {packNames}.',
|
||||
values: {
|
||||
packNames: packsWithConfigPaths.join(', '),
|
||||
},
|
||||
}
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
const CommonUseField = getUseField({ component: Field });
|
||||
|
||||
|
@ -67,6 +165,16 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
|
|||
defaultValue: {
|
||||
config: JSON.stringify(get(newPolicy, 'inputs[0].config.osquery.value', {}), null, 2),
|
||||
},
|
||||
serializer: (formData) => {
|
||||
let config;
|
||||
try {
|
||||
// @ts-expect-error update types
|
||||
config = JSON.parse(formData.config);
|
||||
} catch (e) {
|
||||
config = {};
|
||||
}
|
||||
return { config };
|
||||
},
|
||||
schema: {
|
||||
config: {
|
||||
label: i18n.translate('xpack.osquery.fleetIntegration.osqueryConfig.configFieldLabel', {
|
||||
|
@ -82,35 +190,63 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
|
|||
{ allowEmptyString: true }
|
||||
),
|
||||
},
|
||||
{ validator: packConfigFilesValidator },
|
||||
{
|
||||
validator: configProtectedKeysValidator,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { isValid, getFormData } = configForm;
|
||||
const [{ config }] = useFormData({ form: configForm, watch: 'config' });
|
||||
const { isValid, setFieldValue } = configForm;
|
||||
|
||||
const agentsLinkHref = useMemo(() => {
|
||||
if (!policy?.policy_id) return '#';
|
||||
|
||||
return getUrlForApp(PLUGIN_ID, {
|
||||
path:
|
||||
`#` +
|
||||
pagePathGetters.policy_details({ policyId: policy?.policy_id })[1] +
|
||||
'?openEnrollmentFlyout=true',
|
||||
path: pagePathGetters.policy_details({ policyId: policy?.policy_id })[1],
|
||||
});
|
||||
}, [getUrlForApp, policy?.policy_id]);
|
||||
|
||||
const handleConfigUpload = useCallback(
|
||||
(newConfig) => {
|
||||
let currentPacks = {};
|
||||
try {
|
||||
currentPacks = JSON.parse(config)?.packs;
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (e) {}
|
||||
|
||||
if (newConfig) {
|
||||
setFieldValue(
|
||||
'config',
|
||||
JSON.stringify(
|
||||
{
|
||||
...newConfig,
|
||||
...(currentPacks || newConfig.packs
|
||||
? { packs: { ...newConfig.packs, ...currentPacks } }
|
||||
: {}),
|
||||
},
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
}
|
||||
},
|
||||
[config, setFieldValue]
|
||||
);
|
||||
|
||||
useDebounce(
|
||||
() => {
|
||||
// if undefined it means that config was not modified
|
||||
if (isValid === undefined) return;
|
||||
const configData = getFormData().config;
|
||||
|
||||
const updatedPolicy = produce(newPolicy, (draft) => {
|
||||
if (isEmpty(configData)) {
|
||||
if (isEmpty(config)) {
|
||||
unset(draft, 'inputs[0].config');
|
||||
} else {
|
||||
set(draft, 'inputs[0].config.osquery.value', configData);
|
||||
set(draft, 'inputs[0].config.osquery.value', config);
|
||||
}
|
||||
return draft;
|
||||
});
|
||||
|
@ -118,7 +254,7 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
|
|||
onChange({ isValid: !!isValid, updatedPolicy: isValid ? updatedPolicy : newPolicy });
|
||||
},
|
||||
500,
|
||||
[isValid]
|
||||
[isValid, config]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -220,11 +356,7 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
|
|||
</>
|
||||
) : null}
|
||||
|
||||
<NavigationButtons
|
||||
isDisabled={!editMode}
|
||||
integrationPolicyId={policy?.id}
|
||||
agentPolicyId={policy?.policy_id}
|
||||
/>
|
||||
<NavigationButtons isDisabled={!editMode} agentPolicyId={policy?.policy_id} />
|
||||
<EuiSpacer size="xxl" />
|
||||
<StyledEuiAccordion
|
||||
id="advanced"
|
||||
|
@ -238,6 +370,7 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
|
|||
<EuiSpacer size="xs" />
|
||||
<Form form={configForm}>
|
||||
<CommonUseField path="config" />
|
||||
<ConfigUploader onChange={handleConfigUpload} />
|
||||
</Form>
|
||||
</StyledEuiAccordion>
|
||||
</>
|
||||
|
|
|
@ -48,14 +48,19 @@ const LiveQueryComponent: React.FC<LiveQueryProps> = ({
|
|||
const { data: hasActionResultsPrivileges, isFetched } = useActionResultsPrivileges();
|
||||
|
||||
const defaultValue = useMemo(() => {
|
||||
if (agentId || agentPolicyIds || query) {
|
||||
if (agentId || agentPolicyIds?.length || query?.length) {
|
||||
const agentSelection =
|
||||
agentId || agentPolicyIds?.length
|
||||
? {
|
||||
allAgentsSelected: false,
|
||||
agents: castArray(agentId ?? agentIds ?? []),
|
||||
platformsSelected: [],
|
||||
policiesSelected: agentPolicyIds ?? [],
|
||||
}
|
||||
: null;
|
||||
|
||||
return {
|
||||
agentSelection: {
|
||||
allAgentsSelected: false,
|
||||
agents: castArray(agentId ?? agentIds ?? []),
|
||||
platformsSelected: [],
|
||||
policiesSelected: agentPolicyIds ?? [],
|
||||
},
|
||||
...(agentSelection ? { agentSelection } : {}),
|
||||
query,
|
||||
savedQueryId,
|
||||
ecs_mapping,
|
||||
|
|
|
@ -5,9 +5,17 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiInMemoryTable, EuiBasicTableColumn, EuiLink, EuiToolTip } from '@elastic/eui';
|
||||
import {
|
||||
EuiButtonEmpty,
|
||||
EuiText,
|
||||
EuiPopover,
|
||||
EuiInMemoryTable,
|
||||
EuiBasicTableColumn,
|
||||
EuiLink,
|
||||
EuiToolTip,
|
||||
} from '@elastic/eui';
|
||||
import moment from 'moment-timezone';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
@ -15,6 +23,7 @@ import { PackagePolicy } from '../../../fleet/common';
|
|||
import { useRouterNavigate } from '../common/lib/kibana';
|
||||
import { usePacks } from './use_packs';
|
||||
import { ActiveStateSwitch } from './active_state_switch';
|
||||
import { AgentsPolicyLink } from '../agent_policies/agents_policy_link';
|
||||
|
||||
const UpdatedBy = styled.span`
|
||||
white-space: nowrap;
|
||||
|
@ -32,10 +41,53 @@ const renderName = (_: unknown, item: { id: string; attributes: { name: string }
|
|||
<ScheduledQueryName id={item.id} name={item.attributes.name} />
|
||||
);
|
||||
|
||||
export const AgentPoliciesPopover = ({ agentPolicyIds }: { agentPolicyIds: string[] }) => {
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
||||
|
||||
const onButtonClick = useCallback(
|
||||
() => setIsPopoverOpen((currentIsPopoverOpen) => !currentIsPopoverOpen),
|
||||
[]
|
||||
);
|
||||
const closePopover = useCallback(() => setIsPopoverOpen(false), []);
|
||||
|
||||
const button = useMemo(
|
||||
() => (
|
||||
<EuiButtonEmpty flush="both" onClick={onButtonClick}>
|
||||
<>{agentPolicyIds?.length ?? 0}</>
|
||||
</EuiButtonEmpty>
|
||||
),
|
||||
[agentPolicyIds?.length, onButtonClick]
|
||||
);
|
||||
|
||||
if (!agentPolicyIds?.length) {
|
||||
return <>{agentPolicyIds?.length ?? 0}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiPopover
|
||||
button={button}
|
||||
isOpen={isPopoverOpen}
|
||||
closePopover={closePopover}
|
||||
initialFocus={false}
|
||||
>
|
||||
<EuiText size="s">
|
||||
{agentPolicyIds?.map((policyId) => (
|
||||
<div key={policyId}>
|
||||
<AgentsPolicyLink policyId={policyId} />
|
||||
</div>
|
||||
))}
|
||||
</EuiText>
|
||||
</EuiPopover>
|
||||
);
|
||||
};
|
||||
|
||||
const PacksTableComponent = () => {
|
||||
const { data } = usePacks({});
|
||||
|
||||
const renderAgentPolicy = useCallback((policyIds) => <>{policyIds?.length ?? 0}</>, []);
|
||||
const renderAgentPolicy = useCallback(
|
||||
(agentPolicyIds) => <AgentPoliciesPopover agentPolicyIds={agentPolicyIds} />,
|
||||
[]
|
||||
);
|
||||
|
||||
const renderQueries = useCallback(
|
||||
(queries) => <>{(queries && Object.keys(queries).length) ?? 0}</>,
|
||||
|
|
|
@ -93,6 +93,7 @@ const StyledFieldSpan = styled.span`
|
|||
// align the icon to the inputs
|
||||
const StyledButtonWrapper = styled.div`
|
||||
margin-top: 11px;
|
||||
width: 24px;
|
||||
`;
|
||||
|
||||
const ECSFieldWrapper = styled(EuiFlexItem)`
|
||||
|
@ -476,12 +477,19 @@ export const ECSMappingEditorForm = forwardRef<ECSMappingEditorFormRef, ECSMappi
|
|||
[__validateFields, editForm, formData, validate]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (onAdd && !deepEqual(formData, currentFormData.current)) {
|
||||
currentFormData.current = formData;
|
||||
handleSubmit();
|
||||
}
|
||||
}, [handleSubmit, formData, onAdd]);
|
||||
|
||||
useEffect(() => {
|
||||
if (onChange && !deepEqual(formData, currentFormData.current)) {
|
||||
currentFormData.current = formData;
|
||||
onChange(formData);
|
||||
}
|
||||
}, [defaultValue, formData, onChange]);
|
||||
}, [defaultValue, formData, handleDeleteClick, onChange]);
|
||||
|
||||
useEffect(() => {
|
||||
if (defaultValue) {
|
||||
|
@ -497,18 +505,15 @@ export const ECSMappingEditorForm = forwardRef<ECSMappingEditorFormRef, ECSMappi
|
|||
<EuiFlexGroup alignItems="flexStart" gutterSize="s" wrap>
|
||||
<EuiFlexItem>
|
||||
<CommonUseField
|
||||
path="value.field"
|
||||
component={OsqueryColumnField}
|
||||
path="key"
|
||||
component={ECSComboboxField}
|
||||
// eslint-disable-next-line react-perf/jsx-no-new-object-as-prop
|
||||
euiFieldProps={{
|
||||
options: osquerySchemaOptions,
|
||||
isDisabled,
|
||||
}}
|
||||
euiFieldProps={{ isDisabled }}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<StyledButtonWrapper>
|
||||
<EuiIcon type="arrowRight" />
|
||||
<EuiIcon type="arrowLeft" />
|
||||
</StyledButtonWrapper>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
@ -517,16 +522,19 @@ export const ECSMappingEditorForm = forwardRef<ECSMappingEditorFormRef, ECSMappi
|
|||
<EuiFlexGroup alignItems="flexStart" gutterSize="s" wrap>
|
||||
<ECSFieldWrapper>
|
||||
<CommonUseField
|
||||
path="key"
|
||||
component={ECSComboboxField}
|
||||
path="value.field"
|
||||
component={OsqueryColumnField}
|
||||
// eslint-disable-next-line react-perf/jsx-no-new-object-as-prop
|
||||
euiFieldProps={{ isDisabled }}
|
||||
euiFieldProps={{
|
||||
options: osquerySchemaOptions,
|
||||
isDisabled,
|
||||
}}
|
||||
/>
|
||||
</ECSFieldWrapper>
|
||||
{!isDisabled && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<StyledButtonWrapper>
|
||||
{defaultValue ? (
|
||||
{defaultValue && (
|
||||
<EuiButtonIcon
|
||||
aria-label={i18n.translate(
|
||||
'xpack.osquery.pack.queryFlyoutForm.deleteECSMappingRowButtonAriaLabel',
|
||||
|
@ -538,18 +546,6 @@ export const ECSMappingEditorForm = forwardRef<ECSMappingEditorFormRef, ECSMappi
|
|||
color="danger"
|
||||
onClick={handleDeleteClick}
|
||||
/>
|
||||
) : (
|
||||
<EuiButtonIcon
|
||||
aria-label={i18n.translate(
|
||||
'xpack.osquery.pack.queryFlyoutForm.addECSMappingRowButtonAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Add ECS mapping row',
|
||||
}
|
||||
)}
|
||||
iconType="plus"
|
||||
color="primary"
|
||||
onClick={handleSubmit}
|
||||
/>
|
||||
)}
|
||||
</StyledButtonWrapper>
|
||||
</EuiFlexItem>
|
||||
|
@ -873,16 +869,16 @@ export const ECSMappingEditorField = ({
|
|||
<EuiFlexItem>
|
||||
<EuiFormLabel>
|
||||
<FormattedMessage
|
||||
id="xpack.osquery.pack.queryFlyoutForm.osqueryResultFieldLabel"
|
||||
defaultMessage="Osquery result"
|
||||
id="xpack.osquery.pack.queryFlyoutForm.ecsFieldLabel"
|
||||
defaultMessage="ECS field"
|
||||
/>
|
||||
</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel>
|
||||
<FormattedMessage
|
||||
id="xpack.osquery.pack.queryFlyoutForm.ecsFieldLabel"
|
||||
defaultMessage="ECS field"
|
||||
id="xpack.osquery.pack.queryFlyoutForm.osqueryResultFieldLabel"
|
||||
defaultMessage="Osquery result"
|
||||
/>
|
||||
</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -77,7 +77,7 @@ const ResultsTableComponent: React.FC<ResultsTableComponentProps> = ({
|
|||
const getFleetAppUrl = useCallback(
|
||||
(agentId) =>
|
||||
getUrlForApp('fleet', {
|
||||
path: `#` + pagePathGetters.agent_details({ agentId })[1],
|
||||
path: pagePathGetters.agent_details({ agentId })[1],
|
||||
}),
|
||||
[getUrlForApp]
|
||||
);
|
||||
|
|
|
@ -6,7 +6,14 @@
|
|||
*/
|
||||
|
||||
import { get } from 'lodash';
|
||||
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiCodeBlock, EuiSpacer } from '@elastic/eui';
|
||||
import {
|
||||
EuiButtonEmpty,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiCodeBlock,
|
||||
EuiSpacer,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
@ -16,7 +23,6 @@ import { WithHeaderLayout } from '../../../components/layouts';
|
|||
import { useActionDetails } from '../../../actions/use_action_details';
|
||||
import { ResultTabs } from '../../saved_queries/edit/tabs';
|
||||
import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs';
|
||||
import { BetaBadge, BetaBadgeRowWrapper } from '../../../components/beta_badge';
|
||||
|
||||
const LiveQueryDetailsPageComponent = () => {
|
||||
const { actionId } = useParams<{ actionId: string }>();
|
||||
|
@ -37,15 +43,14 @@ const LiveQueryDetailsPageComponent = () => {
|
|||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<BetaBadgeRowWrapper>
|
||||
<EuiText>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="xpack.osquery.liveQueryDetails.pageTitle"
|
||||
defaultMessage="Live query details"
|
||||
/>
|
||||
</h1>
|
||||
<BetaBadge />
|
||||
</BetaBadgeRowWrapper>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
|
@ -13,7 +13,6 @@ import { useKibana, useRouterNavigate } from '../../../common/lib/kibana';
|
|||
import { ActionsTable } from '../../../actions/actions_table';
|
||||
import { WithHeaderLayout } from '../../../components/layouts';
|
||||
import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs';
|
||||
import { BetaBadge, BetaBadgeRowWrapper } from '../../../components/beta_badge';
|
||||
|
||||
const LiveQueriesPageComponent = () => {
|
||||
const permissions = useKibana().services.application.capabilities.osquery;
|
||||
|
@ -24,15 +23,14 @@ const LiveQueriesPageComponent = () => {
|
|||
() => (
|
||||
<EuiFlexGroup direction="column" gutterSize="m">
|
||||
<EuiFlexItem>
|
||||
<BetaBadgeRowWrapper>
|
||||
<EuiText>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="xpack.osquery.liveQueriesHistory.pageTitle"
|
||||
defaultMessage="Live queries history"
|
||||
/>
|
||||
</h1>
|
||||
<BetaBadge />
|
||||
</BetaBadgeRowWrapper>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { useHistory, useLocation } from 'react-router-dom';
|
||||
|
@ -15,7 +15,6 @@ import { WithHeaderLayout } from '../../../components/layouts';
|
|||
import { useRouterNavigate } from '../../../common/lib/kibana';
|
||||
import { LiveQuery } from '../../../live_queries';
|
||||
import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs';
|
||||
import { BetaBadge, BetaBadgeRowWrapper } from '../../../components/beta_badge';
|
||||
|
||||
const NewLiveQueryPageComponent = () => {
|
||||
useBreadcrumbs('live_query_new');
|
||||
|
@ -49,15 +48,14 @@ const NewLiveQueryPageComponent = () => {
|
|||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<BetaBadgeRowWrapper>
|
||||
<EuiText>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="xpack.osquery.newLiveQuery.pageTitle"
|
||||
defaultMessage="New live query"
|
||||
/>
|
||||
</h1>
|
||||
<BetaBadge />
|
||||
</BetaBadgeRowWrapper>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
|
@ -13,7 +13,6 @@ import { WithHeaderLayout } from '../../../components/layouts';
|
|||
import { useRouterNavigate } from '../../../common/lib/kibana';
|
||||
import { PackForm } from '../../../packs/form';
|
||||
import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs';
|
||||
import { BetaBadge, BetaBadgeRowWrapper } from '../../../components/beta_badge';
|
||||
|
||||
const AddPackPageComponent = () => {
|
||||
useBreadcrumbs('pack_add');
|
||||
|
@ -31,12 +30,11 @@ const AddPackPageComponent = () => {
|
|||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<BetaBadgeRowWrapper>
|
||||
<EuiText>
|
||||
<h1>
|
||||
<FormattedMessage id="xpack.osquery.addPack.pageTitle" defaultMessage="Add pack" />
|
||||
</h1>
|
||||
<BetaBadge />
|
||||
</BetaBadgeRowWrapper>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
|
|
|
@ -26,8 +26,8 @@ import { WithHeaderLayout } from '../../../components/layouts';
|
|||
import { usePack } from '../../../packs/use_pack';
|
||||
import { PackQueriesStatusTable } from '../../../packs/pack_queries_status_table';
|
||||
import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs';
|
||||
import { BetaBadge, BetaBadgeRowWrapper } from '../../../components/beta_badge';
|
||||
import { useAgentPolicyAgentIds } from '../../../agents/use_agent_policy_agent_ids';
|
||||
import { AgentPoliciesPopover } from '../../../packs/packs_table';
|
||||
|
||||
const Divider = styled.div`
|
||||
width: 0;
|
||||
|
@ -69,7 +69,7 @@ const PackDetailsPageComponent = () => {
|
|||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<BetaBadgeRowWrapper>
|
||||
<EuiText>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="xpack.osquery.packDetails.pageTitle"
|
||||
|
@ -80,8 +80,7 @@ const PackDetailsPageComponent = () => {
|
|||
}}
|
||||
/>
|
||||
</h1>
|
||||
<BetaBadge />
|
||||
</BetaBadgeRowWrapper>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
{data?.description && (
|
||||
<EuiFlexItem>
|
||||
|
@ -111,7 +110,7 @@ const PackDetailsPageComponent = () => {
|
|||
<EuiDescriptionListDescription className="eui-textNoWrap">
|
||||
{
|
||||
// @ts-expect-error update types
|
||||
data?.policy_ids?.length
|
||||
<AgentPoliciesPopover agentPolicyIds={data?.policy_ids} />
|
||||
}
|
||||
</EuiDescriptionListDescription>
|
||||
</EuiDescriptionList>
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiLoadingContent,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
|
@ -24,7 +25,6 @@ import { usePack } from '../../../packs/use_pack';
|
|||
import { useDeletePack } from '../../../packs/use_delete_pack';
|
||||
|
||||
import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs';
|
||||
import { BetaBadge, BetaBadgeRowWrapper } from '../../../components/beta_badge';
|
||||
|
||||
const EditPackPageComponent = () => {
|
||||
const { packId } = useParams<{ packId: string }>();
|
||||
|
@ -67,7 +67,7 @@ const EditPackPageComponent = () => {
|
|||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<BetaBadgeRowWrapper>
|
||||
<EuiText>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="xpack.osquery.editPack.pageTitle"
|
||||
|
@ -78,8 +78,7 @@ const EditPackPageComponent = () => {
|
|||
}}
|
||||
/>
|
||||
</h1>
|
||||
<BetaBadge />
|
||||
</BetaBadgeRowWrapper>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
|
|
|
@ -5,14 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
import { useKibana, useRouterNavigate } from '../../../common/lib/kibana';
|
||||
import { WithHeaderLayout } from '../../../components/layouts';
|
||||
import { PacksTable } from '../../../packs/packs_table';
|
||||
import { BetaBadge, BetaBadgeRowWrapper } from '../../../components/beta_badge';
|
||||
|
||||
const PacksPageComponent = () => {
|
||||
const permissions = useKibana().services.application.capabilities.osquery;
|
||||
|
@ -22,12 +21,11 @@ const PacksPageComponent = () => {
|
|||
() => (
|
||||
<EuiFlexGroup direction="column" gutterSize="m">
|
||||
<EuiFlexItem>
|
||||
<BetaBadgeRowWrapper>
|
||||
<EuiText>
|
||||
<h1>
|
||||
<FormattedMessage id="xpack.osquery.packList.pageTitle" defaultMessage="Packs" />
|
||||
</h1>
|
||||
<BetaBadge />
|
||||
</BetaBadgeRowWrapper>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiConfirmModal,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import { isEmpty } from 'lodash/fp';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
|
@ -20,7 +21,6 @@ import { useParams } from 'react-router-dom';
|
|||
import { useKibana, useRouterNavigate } from '../../../common/lib/kibana';
|
||||
import { WithHeaderLayout } from '../../../components/layouts';
|
||||
import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs';
|
||||
import { BetaBadge, BetaBadgeRowWrapper } from '../../../components/beta_badge';
|
||||
import { EditSavedQueryForm } from './form';
|
||||
import { useDeleteSavedQuery, useUpdateSavedQuery, useSavedQuery } from '../../../saved_queries';
|
||||
|
||||
|
@ -65,7 +65,7 @@ const EditSavedQueryPageComponent = () => {
|
|||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<BetaBadgeRowWrapper>
|
||||
<EuiText>
|
||||
<h1>
|
||||
{viewMode ? (
|
||||
<FormattedMessage
|
||||
|
@ -87,8 +87,7 @@ const EditSavedQueryPageComponent = () => {
|
|||
/>
|
||||
)}
|
||||
</h1>
|
||||
<BetaBadge />
|
||||
</BetaBadgeRowWrapper>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
EuiButtonIcon,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
@ -23,7 +24,6 @@ import { ECSMapping } from '../../../../common/schemas/common';
|
|||
import { WithHeaderLayout } from '../../../components/layouts';
|
||||
import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs';
|
||||
import { useKibana, useRouterNavigate } from '../../../common/lib/kibana';
|
||||
import { BetaBadge, BetaBadgeRowWrapper } from '../../../components/beta_badge';
|
||||
import { useSavedQueries } from '../../../saved_queries/use_saved_queries';
|
||||
|
||||
type SavedQuerySO = SavedObject<{
|
||||
|
@ -218,15 +218,14 @@ const SavedQueriesPageComponent = () => {
|
|||
() => (
|
||||
<EuiFlexGroup alignItems="flexStart" direction="column" gutterSize="m">
|
||||
<EuiFlexItem>
|
||||
<BetaBadgeRowWrapper>
|
||||
<EuiText>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="xpack.osquery.savedQueryList.pageTitle"
|
||||
defaultMessage="Saved queries"
|
||||
/>
|
||||
</h1>
|
||||
<BetaBadge />
|
||||
</BetaBadgeRowWrapper>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
|
|
|
@ -5,14 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
|
||||
import React, { useMemo } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
import { useRouterNavigate } from '../../../common/lib/kibana';
|
||||
import { WithHeaderLayout } from '../../../components/layouts';
|
||||
import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs';
|
||||
import { BetaBadge, BetaBadgeRowWrapper } from '../../../components/beta_badge';
|
||||
import { NewSavedQueryForm } from './form';
|
||||
import { useCreateSavedQuery } from '../../../saved_queries/use_create_saved_query';
|
||||
|
||||
|
@ -34,15 +33,14 @@ const NewSavedQueryPageComponent = () => {
|
|||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<BetaBadgeRowWrapper>
|
||||
<EuiText>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="xpack.osquery.addSavedQuery.pageTitle"
|
||||
defaultMessage="Add saved query"
|
||||
/>
|
||||
</h1>
|
||||
<BetaBadge />
|
||||
</BetaBadgeRowWrapper>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
|
|
|
@ -156,7 +156,12 @@ const SavedQueryFormComponent = forwardRef<SavedQueryFormRefObject, SavedQueryFo
|
|||
<CommonUseField path="platform" component={PlatformCheckBoxGroupField} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
{playgroundVisible && <PlaygroundFlyout enabled={isValid} onClose={handleHidePlayground} />}
|
||||
{playgroundVisible && (
|
||||
<PlaygroundFlyout
|
||||
enabled={isValid !== undefined ? isValid : true}
|
||||
onClose={handleHidePlayground}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { map, partialRight, pick } from 'lodash';
|
||||
import { find, map, partialRight, pick } from 'lodash';
|
||||
import { promises as fs } from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
import { run } from '@kbn/dev-utils';
|
||||
|
||||
const OSQUERY_COLUMN_SCHEMA_FIELDS = ['name', 'description', 'platforms', 'columns'];
|
||||
const ELASTIC_OSQUERY_HOSTFS_TABLES = ['users', 'groups', 'processes'];
|
||||
|
||||
run(
|
||||
async ({ flags }) => {
|
||||
|
@ -20,9 +21,14 @@ run(
|
|||
const schemaData = await require(schemaFile);
|
||||
|
||||
const formattedSchema = map(schemaData, partialRight(pick, OSQUERY_COLUMN_SCHEMA_FIELDS));
|
||||
const elasticTables = map(ELASTIC_OSQUERY_HOSTFS_TABLES, (tableName) => ({
|
||||
...find(formattedSchema, { name: tableName }),
|
||||
name: `host_${tableName}`,
|
||||
}));
|
||||
formattedSchema.push(...elasticTables);
|
||||
|
||||
await fs.writeFile(
|
||||
path.join(schemaPath, `v${flags.schema_version}-formatted.json`),
|
||||
path.join(schemaPath, `${flags.schema_version}`),
|
||||
JSON.stringify(formattedSchema)
|
||||
);
|
||||
},
|
||||
|
|
|
@ -17,6 +17,7 @@ import { PLUGIN_ID, OSQUERY_INTEGRATION_NAME } from '../../../common';
|
|||
import { IRouter } from '../../../../../../src/core/server';
|
||||
import { OsqueryAppContext } from '../../lib/osquery_app_context_services';
|
||||
import { convertPackQueriesToSO } from '../pack/utils';
|
||||
import { getInternalSavedObjectsClient } from '../../usage/collector';
|
||||
|
||||
export const createStatusRoute = (router: IRouter, osqueryContext: OsqueryAppContext) => {
|
||||
router.get(
|
||||
|
@ -27,18 +28,21 @@ export const createStatusRoute = (router: IRouter, osqueryContext: OsqueryAppCon
|
|||
},
|
||||
async (context, request, response) => {
|
||||
const esClient = context.core.elasticsearch.client.asInternalUser;
|
||||
const soClient = context.core.savedObjects.client;
|
||||
const internalSavedObjectsClient = await getInternalSavedObjectsClient(
|
||||
osqueryContext.getStartServices
|
||||
);
|
||||
const packageService = osqueryContext.service.getPackageService();
|
||||
const packagePolicyService = osqueryContext.service.getPackagePolicyService();
|
||||
const agentPolicyService = osqueryContext.service.getAgentPolicyService();
|
||||
|
||||
const packageInfo = await osqueryContext.service
|
||||
.getPackageService()
|
||||
?.getInstallation({ savedObjectsClient: soClient, pkgName: OSQUERY_INTEGRATION_NAME });
|
||||
const packageInfo = await osqueryContext.service.getPackageService()?.getInstallation({
|
||||
savedObjectsClient: internalSavedObjectsClient,
|
||||
pkgName: OSQUERY_INTEGRATION_NAME,
|
||||
});
|
||||
|
||||
if (packageInfo?.install_version && satisfies(packageInfo?.install_version, '<0.6.0')) {
|
||||
try {
|
||||
const policyPackages = await packagePolicyService?.list(soClient, {
|
||||
const policyPackages = await packagePolicyService?.list(internalSavedObjectsClient, {
|
||||
kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:${OSQUERY_INTEGRATION_NAME}`,
|
||||
perPage: 10000,
|
||||
page: 1,
|
||||
|
@ -99,7 +103,7 @@ export const createStatusRoute = (router: IRouter, osqueryContext: OsqueryAppCon
|
|||
|
||||
await packageService?.ensureInstalledPackage({
|
||||
esClient,
|
||||
savedObjectsClient: soClient,
|
||||
savedObjectsClient: internalSavedObjectsClient,
|
||||
pkgName: OSQUERY_INTEGRATION_NAME,
|
||||
});
|
||||
|
||||
|
@ -110,12 +114,15 @@ export const createStatusRoute = (router: IRouter, osqueryContext: OsqueryAppCon
|
|||
// @ts-expect-error update types
|
||||
pack.policy_ids.includes(key)
|
||||
);
|
||||
await packagePolicyService?.upgrade(soClient, esClient, [value]);
|
||||
const packagePolicy = await packagePolicyService?.get(soClient, value);
|
||||
await packagePolicyService?.upgrade(internalSavedObjectsClient, esClient, [value]);
|
||||
const packagePolicy = await packagePolicyService?.get(
|
||||
internalSavedObjectsClient,
|
||||
value
|
||||
);
|
||||
|
||||
if (packagePolicy) {
|
||||
return packagePolicyService?.update(
|
||||
soClient,
|
||||
internalSavedObjectsClient,
|
||||
esClient,
|
||||
packagePolicy.id,
|
||||
produce(packagePolicy, (draft) => {
|
||||
|
@ -147,13 +154,13 @@ export const createStatusRoute = (router: IRouter, osqueryContext: OsqueryAppCon
|
|||
|
||||
const agentPolicyIds = uniq(map(policyPackages?.items, 'policy_id'));
|
||||
const agentPolicies = mapKeys(
|
||||
await agentPolicyService?.getByIds(soClient, agentPolicyIds),
|
||||
await agentPolicyService?.getByIds(internalSavedObjectsClient, agentPolicyIds),
|
||||
'id'
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
map(migrationObject.packs, async (packObject) => {
|
||||
await soClient.create(
|
||||
await internalSavedObjectsClient.create(
|
||||
packSavedObjectType,
|
||||
{
|
||||
// @ts-expect-error update types
|
||||
|
@ -183,7 +190,7 @@ export const createStatusRoute = (router: IRouter, osqueryContext: OsqueryAppCon
|
|||
);
|
||||
|
||||
await packagePolicyService?.delete(
|
||||
soClient,
|
||||
internalSavedObjectsClient,
|
||||
esClient,
|
||||
migrationObject.packagePoliciesToDelete
|
||||
);
|
||||
|
|
|
@ -18834,8 +18834,6 @@
|
|||
"xpack.osquery.breadcrumbs.newSavedQueryPageTitle": "新規",
|
||||
"xpack.osquery.breadcrumbs.overviewPageTitle": "概要",
|
||||
"xpack.osquery.breadcrumbs.savedQueriesPageTitle": "保存されたクエリ",
|
||||
"xpack.osquery.common.tabBetaBadgeLabel": "ベータ",
|
||||
"xpack.osquery.common.tabBetaBadgeTooltipContent": "この機能は現在開発中です。他にも機能が追加され、機能によっては変更されるものもあります。",
|
||||
"xpack.osquery.editSavedQuery.deleteSavedQueryButtonLabel": "クエリを削除",
|
||||
"xpack.osquery.editSavedQuery.deleteSuccessToastMessageText": "保存されたクエリが正常に削除されました。",
|
||||
"xpack.osquery.editSavedQuery.form.cancelButtonLabel": "キャンセル",
|
||||
|
|
|
@ -19105,8 +19105,6 @@
|
|||
"xpack.osquery.breadcrumbs.newSavedQueryPageTitle": "新建",
|
||||
"xpack.osquery.breadcrumbs.overviewPageTitle": "概览",
|
||||
"xpack.osquery.breadcrumbs.savedQueriesPageTitle": "已保存查询",
|
||||
"xpack.osquery.common.tabBetaBadgeLabel": "公测版",
|
||||
"xpack.osquery.common.tabBetaBadgeTooltipContent": "我们正在开发此功能。将会有更多的功能,某些功能可能有变更。",
|
||||
"xpack.osquery.createScheduledQuery.agentPolicyAgentsCountText": "{count, plural, other {# 个代理}}已注册",
|
||||
"xpack.osquery.editSavedQuery.deleteSavedQueryButtonLabel": "删除查询",
|
||||
"xpack.osquery.editSavedQuery.deleteSuccessToastMessageText": "已成功删除已保存查询",
|
||||
|
|
|
@ -24093,10 +24093,10 @@ react-popper@^2.2.4:
|
|||
react-fast-compare "^3.0.1"
|
||||
warning "^4.0.2"
|
||||
|
||||
react-query@^3.27.0:
|
||||
version "3.27.0"
|
||||
resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.27.0.tgz#77c76377ae41d180c4718da07ef72df82e07306b"
|
||||
integrity sha512-2MR5LBXnR6OMXQVLcv/57x1zkDNj6gK5J5mtjGi6pu0aQ6Y4jGQysVvkrAErMKMZJVZELFcYGA8LsGIHzlo/zg==
|
||||
react-query@^3.28.0:
|
||||
version "3.28.0"
|
||||
resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.28.0.tgz#1bfe12944860b2b773680054de37f19438f59d1d"
|
||||
integrity sha512-OeX+nRqs7Zi0MvvtaKxKWE4N966UGtqSVuedOsz8cJh9eW195fgtYZ9nW3hZjIPPmeDY1PkArLUiV4wZvNRDPw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.5.5"
|
||||
broadcast-channel "^3.4.1"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue