Skip to content

Commit

Permalink
[Security Solution] Initiate endpoint package upgrade from security a…
Browse files Browse the repository at this point in the history
…pp (elastic#77498)

* Working on package update functionality

* Correctly installing package

* Moving upgrade component and working upgrade

* Doing permissions check

* Cleaning up imports

* Adding bulk upgrade api

* Addressing comments

* Removing todo

* Changing body field

* Adding helper for getting the bulk install route

* Adding request spec

* Using bulk install endpoint from ingest

* Moving component to a hook

* Addressing feedback
  • Loading branch information
jonathan-buttner authored and scottybollinger committed Sep 28, 2020
1 parent 40d988a commit b731b01
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 0 deletions.
7 changes: 7 additions & 0 deletions x-pack/plugins/security_solution/public/app/home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { useInitSourcerer, useSourcererScope } from '../../common/containers/sou
import { useKibana } from '../../common/lib/kibana';
import { DETECTIONS_SUB_PLUGIN_ID } from '../../../common/constants';
import { SourcererScopeName } from '../../common/store/sourcerer/model';
import { useUpgradeEndpointPackage } from '../../common/hooks/endpoint/upgrade';
import { useThrottledResizeObserver } from '../../common/components/utils';

const Main = styled.main.attrs<{ paddingTop: number }>(({ paddingTop }) => ({
Expand Down Expand Up @@ -58,6 +59,12 @@ const HomePageComponent: React.FC<HomePageProps> = ({ children }) => {
const [showTimeline] = useShowTimeline();

const { browserFields, indexPattern, indicesExist } = useSourcererScope();
// side effect: this will attempt to upgrade the endpoint package if it is not up to date
// this will run when a user navigates to the Security Solution app and when they navigate between
// tabs in the app. This is useful for keeping the endpoint package as up to date as possible until
// a background task solution can be built on the server side. Once a background task solution is available we
// can remove this.
useUpgradeEndpointPackage();

return (
<SecuritySolutionAppWrapper>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { useEffect } from 'react';
import { HttpFetchOptions, HttpStart } from 'src/core/public';
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
import {
epmRouteService,
appRoutesService,
CheckPermissionsResponse,
BulkInstallPackagesResponse,
} from '../../../../../ingest_manager/common';
import { StartServices } from '../../../types';
import { useIngestEnabledCheck } from './ingest_enabled';

/**
* Requests that the endpoint package be upgraded to the latest version
*
* @param http an http client for sending the request
* @param options an object containing options for the request
*/
const sendUpgradeEndpointPackage = async (
http: HttpStart,
options: HttpFetchOptions = {}
): Promise<BulkInstallPackagesResponse> => {
return http.post<BulkInstallPackagesResponse>(epmRouteService.getBulkInstallPath(), {
...options,
body: JSON.stringify({
packages: ['endpoint'],
}),
});
};

/**
* Checks with the ingest manager if the current user making these requests has the right permissions
* to install the endpoint package.
*
* @param http an http client for sending the request
* @param options an object containing options for the request
*/
const sendCheckPermissions = async (
http: HttpStart,
options: HttpFetchOptions = {}
): Promise<CheckPermissionsResponse> => {
return http.get<CheckPermissionsResponse>(appRoutesService.getCheckPermissionsPath(), {
...options,
});
};

export const useUpgradeEndpointPackage = () => {
const context = useKibana<StartServices>();
const { allEnabled: ingestEnabled } = useIngestEnabledCheck();

useEffect(() => {
const abortController = new AbortController();

// cancel any ongoing requests
const abortRequests = () => {
abortController.abort();
};

if (ingestEnabled) {
const signal = abortController.signal;

(async () => {
try {
// make sure we're a privileged user before trying to install the package
const { success: hasPermissions } = await sendCheckPermissions(context.services.http, {
signal,
});

// if we're not a privileged user then return and don't try to check the status of the endpoint package
if (!hasPermissions) {
return abortRequests;
}

// ignore the response for now since we aren't notifying the user
await sendUpgradeEndpointPackage(context.services.http, { signal });
} catch (error) {
// Ignore Errors, since this should not hinder the user's ability to use the UI

// ignore the error that occurs from aborting a request
if (!abortController.signal.aborted) {
// eslint-disable-next-line no-console
console.error(error);
}
}

return abortRequests;
})();
}
}, [ingestEnabled, context.services.http]);
};

0 comments on commit b731b01

Please sign in to comment.