mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[EDR Workflows][Osquery] Adapt to policy_ids array instead of policy_id (#193150)
This commit is contained in:
parent
b3b776fb99
commit
299439252c
4 changed files with 91 additions and 49 deletions
|
@ -19,12 +19,12 @@ export const useOsqueryPolicies = () => {
|
|||
return useQuery(
|
||||
['osqueryPolicies'],
|
||||
() =>
|
||||
http.get<{ items: Array<{ policy_id: string }> }>(
|
||||
http.get<{ items: Array<{ policy_id: string; policy_ids: string[] }> }>(
|
||||
'/internal/osquery/fleet_wrapper/package_policies',
|
||||
{ version: API_VERSIONS.internal.v1 }
|
||||
),
|
||||
{
|
||||
select: (response) => uniq<string>(response.items.map((p) => p.policy_id)),
|
||||
select: (response) => uniq<string>(response.items.flatMap((p) => p.policy_ids)),
|
||||
onSuccess: () => setErrorToast(),
|
||||
onError: (error: Error) =>
|
||||
setErrorToast(error, {
|
||||
|
|
|
@ -14,25 +14,29 @@ import { useKibana, isModifiedEvent, isLeftClickEvent } from '../common/lib/kiba
|
|||
|
||||
interface NavigationButtonsProps {
|
||||
isDisabled?: boolean;
|
||||
agentPolicyId?: string | null;
|
||||
agentPolicyIds?: string[];
|
||||
}
|
||||
|
||||
const NavigationButtonsComponent: React.FC<NavigationButtonsProps> = ({
|
||||
isDisabled = false,
|
||||
agentPolicyId,
|
||||
agentPolicyIds,
|
||||
}) => {
|
||||
const {
|
||||
application: { getUrlForApp, navigateToApp },
|
||||
} = useKibana().services;
|
||||
|
||||
const agentPolicyIdsQueryParam = useMemo(
|
||||
() => agentPolicyIds?.map((id) => `agentPolicyId=${id}`).join('&'),
|
||||
[agentPolicyIds]
|
||||
);
|
||||
const liveQueryHref = useMemo(
|
||||
() =>
|
||||
getUrlForApp(PLUGIN_ID, {
|
||||
path: agentPolicyId
|
||||
? `/live_queries/new?agentPolicyId=${agentPolicyId}`
|
||||
path: agentPolicyIds?.length
|
||||
? `/live_queries/new?${agentPolicyIdsQueryParam}`
|
||||
: '/live_queries/new',
|
||||
}),
|
||||
[agentPolicyId, getUrlForApp]
|
||||
[agentPolicyIdsQueryParam, agentPolicyIds?.length, getUrlForApp]
|
||||
);
|
||||
|
||||
const liveQueryClick = useCallback(
|
||||
|
@ -40,13 +44,13 @@ const NavigationButtonsComponent: React.FC<NavigationButtonsProps> = ({
|
|||
if (!isModifiedEvent(event) && isLeftClickEvent(event)) {
|
||||
event.preventDefault();
|
||||
navigateToApp(PLUGIN_ID, {
|
||||
path: agentPolicyId
|
||||
? `/live_queries/new?agentPolicyId=${agentPolicyId}`
|
||||
path: agentPolicyIds?.length
|
||||
? `/live_queries/new?${agentPolicyIdsQueryParam}`
|
||||
: '/live_queries/new',
|
||||
});
|
||||
}
|
||||
},
|
||||
[agentPolicyId, navigateToApp]
|
||||
[agentPolicyIdsQueryParam, agentPolicyIds?.length, navigateToApp]
|
||||
);
|
||||
|
||||
const packsHref = getUrlForApp(PLUGIN_ID, {
|
||||
|
|
|
@ -146,14 +146,21 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
|
|||
policy?: PackagePolicyEditExtensionComponentProps['policy'];
|
||||
}
|
||||
>(({ onChange, policy, newPolicy }) => {
|
||||
const [policyAgentsCount, setPolicyAgentsCount] = useState<number | null>(null);
|
||||
const [agentPolicy, setAgentPolicy] = useState<AgentPolicy | null>(null);
|
||||
const [agentlessPolicyIds, setAgentlessPolicyIds] = useState<string[]>([]);
|
||||
const [agentPolicies, setAgentPolicies] = useState<AgentPolicy[]>([]);
|
||||
const [editMode] = useState(!!policy);
|
||||
const {
|
||||
application: { getUrlForApp },
|
||||
http,
|
||||
} = useKibana().services;
|
||||
|
||||
const policyIdsWithAgents = useMemo(
|
||||
() =>
|
||||
agentlessPolicyIds?.length
|
||||
? policy?.policy_ids.filter((id) => !agentlessPolicyIds.includes(id))
|
||||
: policy?.policy_ids,
|
||||
[agentlessPolicyIds, policy?.policy_ids]
|
||||
);
|
||||
const { form: configForm } = useForm({
|
||||
defaultValue: {
|
||||
config: JSON.stringify(get(newPolicy, 'inputs[0].config.osquery.value', {}), null, 2),
|
||||
|
@ -185,13 +192,16 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
|
|||
const [{ config }] = useFormData({ form: configForm, watch: 'config' });
|
||||
const { isValid, setFieldValue } = configForm;
|
||||
|
||||
const agentsLinkHref = useMemo(() => {
|
||||
if (!policy?.policy_id) return '#';
|
||||
const agentsLinkHref = useCallback(
|
||||
(policyId) => {
|
||||
if (!policy?.policy_ids?.length) return '#';
|
||||
|
||||
return getUrlForApp(PLUGIN_ID, {
|
||||
path: pagePathGetters.policy_details({ policyId: policy?.policy_id })[1],
|
||||
});
|
||||
}, [getUrlForApp, policy?.policy_id]);
|
||||
return getUrlForApp(PLUGIN_ID, {
|
||||
path: pagePathGetters.policy_details({ policyId })[1],
|
||||
});
|
||||
},
|
||||
[getUrlForApp, policy?.policy_ids?.length]
|
||||
);
|
||||
|
||||
const handleConfigUpload = useCallback(
|
||||
(newConfig: any) => {
|
||||
|
@ -248,42 +258,57 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
|
|||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (editMode && policyAgentsCount === null) {
|
||||
const policyIdsWithNoAgent: string[] = [];
|
||||
if (editMode && !agentlessPolicyIds?.length) {
|
||||
const fetchAgentsCount = async () => {
|
||||
try {
|
||||
const response = await http.fetch<{ results: { total: number } }>(
|
||||
agentRouteService.getStatusPath(),
|
||||
{
|
||||
query: {
|
||||
policyId: policy?.policy_id,
|
||||
},
|
||||
}
|
||||
);
|
||||
if (response.results) {
|
||||
setPolicyAgentsCount(response.results.total);
|
||||
if (policy?.policy_ids?.length) {
|
||||
await Promise.all(
|
||||
policy.policy_ids.map(async (id: string) => {
|
||||
const response = await http.fetch<{ results: { total: number } }>(
|
||||
agentRouteService.getStatusPath(),
|
||||
{
|
||||
query: {
|
||||
policyId: id,
|
||||
},
|
||||
}
|
||||
);
|
||||
if (response.results.total === 0) {
|
||||
policyIdsWithNoAgent.push(id);
|
||||
}
|
||||
})
|
||||
);
|
||||
setAgentlessPolicyIds(policyIdsWithNoAgent);
|
||||
}
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (e) {}
|
||||
};
|
||||
|
||||
const fetchAgentPolicyDetails = async () => {
|
||||
if (policy?.policy_id) {
|
||||
if (policyIdsWithNoAgent?.length) {
|
||||
const policiesWithoutAgent: AgentPolicy[] = [];
|
||||
try {
|
||||
const response = await http.fetch<{ item: AgentPolicy }>(
|
||||
agentPolicyRouteService.getInfoPath(policy?.policy_id)
|
||||
await Promise.all(
|
||||
policyIdsWithNoAgent.map(async (id) => {
|
||||
const response = await http.fetch<{ item: AgentPolicy }>(
|
||||
agentPolicyRouteService.getInfoPath(id)
|
||||
);
|
||||
if (response.item) {
|
||||
policiesWithoutAgent.push(response.item);
|
||||
}
|
||||
})
|
||||
);
|
||||
if (response.item) {
|
||||
setAgentPolicy(response.item);
|
||||
if (policiesWithoutAgent.length) {
|
||||
setAgentPolicies(policiesWithoutAgent);
|
||||
}
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (e) {}
|
||||
}
|
||||
};
|
||||
|
||||
fetchAgentsCount();
|
||||
fetchAgentPolicyDetails();
|
||||
fetchAgentsCount().then(() => fetchAgentPolicyDetails());
|
||||
}
|
||||
}, [editMode, http, policy?.policy_id, policyAgentsCount]);
|
||||
}, [editMode, http, agentlessPolicyIds?.length, agentlessPolicyIds, policy?.policy_ids]);
|
||||
|
||||
useEffect(() => {
|
||||
/*
|
||||
|
@ -363,21 +388,30 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
|
|||
return (
|
||||
<>
|
||||
{!editMode ? <DisabledCallout /> : null}
|
||||
{policyAgentsCount === 0 ? (
|
||||
{agentlessPolicyIds?.length ? (
|
||||
<>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiCallOut title="No agents in the policy" color="warning" iconType="help">
|
||||
<p>
|
||||
{`Fleet has detected that you have not assigned yet any agent to the `}
|
||||
{
|
||||
<EuiLink href={agentsLinkHref}>
|
||||
{agentPolicy?.name ?? policy?.policy_id}
|
||||
</EuiLink>
|
||||
}
|
||||
{i18n.translate(
|
||||
'xpack.osquery.fleetIntegration.osqueryConfig.noAgentsWarningMessage',
|
||||
{
|
||||
defaultMessage:
|
||||
'Fleet has detected that you have not assigned yet any agent to the ',
|
||||
}
|
||||
)}
|
||||
{agentPolicies?.map((agentPolicy, index) => (
|
||||
<React.Fragment key={agentPolicy.id}>
|
||||
<EuiLink href={agentsLinkHref(agentPolicy.id)}>
|
||||
{agentPolicy.name || agentPolicy?.id}
|
||||
</EuiLink>
|
||||
{index < agentPolicies.length - 1 && `, `}
|
||||
</React.Fragment>
|
||||
))}
|
||||
{`. `}
|
||||
<br />
|
||||
<strong>{`Only agents within the policy with active Osquery Manager integration support the functionality presented below.`}</strong>
|
||||
<strong>{`Only agents within the policies with active Osquery Manager integration support the functionality presented below.`}</strong>
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
</EuiFlexItem>
|
||||
|
@ -385,10 +419,9 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
|
|||
<EuiSpacer />
|
||||
</>
|
||||
) : null}
|
||||
|
||||
{!permissionDenied && (
|
||||
<>
|
||||
<NavigationButtons isDisabled={!editMode} agentPolicyId={policy?.policy_id} />
|
||||
<NavigationButtons isDisabled={!editMode} agentPolicyIds={policyIdsWithAgents} />
|
||||
<EuiSpacer size="xxl" />
|
||||
<EuiAccordion
|
||||
css={euiAccordionCss}
|
||||
|
|
|
@ -11,6 +11,7 @@ import React, { useEffect, useMemo, useState } from 'react';
|
|||
import { useHistory, useLocation } from 'react-router-dom';
|
||||
import qs from 'query-string';
|
||||
|
||||
import { isArray } from 'lodash';
|
||||
import { WithHeaderLayout } from '../../../components/layouts';
|
||||
import { useRouterNavigate } from '../../../common/lib/kibana';
|
||||
import { LiveQuery } from '../../../live_queries';
|
||||
|
@ -30,7 +31,11 @@ const NewLiveQueryPageComponent = () => {
|
|||
const agentPolicyIds = useMemo(() => {
|
||||
const queryParams = qs.parse(location.search);
|
||||
|
||||
return queryParams?.agentPolicyId ? ([queryParams?.agentPolicyId] as string[]) : undefined;
|
||||
return queryParams?.agentPolicyId
|
||||
? isArray(queryParams?.agentPolicyId)
|
||||
? queryParams?.agentPolicyId
|
||||
: [queryParams?.agentPolicyId]
|
||||
: undefined;
|
||||
}, [location.search]);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -68,7 +73,7 @@ const NewLiveQueryPageComponent = () => {
|
|||
|
||||
return (
|
||||
<WithHeaderLayout leftColumn={LeftColumn}>
|
||||
<LiveQuery agentPolicyIds={agentPolicyIds} {...initialFormData} />
|
||||
<LiveQuery {...initialFormData} agentPolicyIds={agentPolicyIds} />
|
||||
</WithHeaderLayout>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue