[Security Solution][Endpoint] Fix bug where users without superuser role are not able to see Endpoint data on Host Details (#116202) (#116647)

* Add `.catch()` statement to ES calls in order to get better stacktraces
* Improve efficiency of getHostEndpoint() search strategy method
* Refactor `getHostEndpoint()` to use new Metadata service as well as the internal kibana ES client

Co-authored-by: Paul Tavares <56442535+paul-tavares@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2021-11-01 10:18:07 -04:00 committed by GitHub
parent 85edf7820d
commit 9e1c27458a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 41 deletions

View file

@ -41,7 +41,7 @@ import { findAllUnenrolledAgentIds } from './support/unenroll';
import { getAllEndpointPackagePolicies } from './support/endpoint_package_policies';
import { findAgentIdsByStatus } from './support/agent_status';
import { EndpointAppContextService } from '../../endpoint_app_context_services';
import { fleetAgentStatusToEndpointHostStatus } from '../../utils';
import { catchAndWrapError, fleetAgentStatusToEndpointHostStatus } from '../../utils';
import {
queryResponseToHostListResult,
queryResponseToHostResult,
@ -194,7 +194,9 @@ export async function getHostMetaData(
const query = getESQueryHostMetadataByID(id);
const response = await esClient.asCurrentUser.search<HostMetadata>(query);
const response = await esClient.asCurrentUser
.search<HostMetadata>(query)
.catch(catchAndWrapError);
const hostResult = queryResponseToHostResult(response.body);

View file

@ -22,9 +22,7 @@ import {
HostValue,
} from '../../../../../../common/search_strategy/security_solution/hosts';
import { toObjectArrayOfStrings } from '../../../../../../common/utils/to_array';
import { getHostMetaData } from '../../../../../endpoint/routes/metadata/handlers';
import { EndpointAppContext } from '../../../../../endpoint/types';
import { fleetAgentStatusToEndpointHostStatus } from '../../../../../endpoint/utils';
import { getPendingActionCounts } from '../../../../../endpoint/services';
export const HOST_FIELDS = [
@ -184,51 +182,54 @@ export const getHostEndpoint = async (
endpointContext: EndpointAppContext;
}
): Promise<EndpointFields | null> => {
const { esClient, endpointContext, savedObjectsClient } = deps;
if (!id) {
return null;
}
const { esClient, endpointContext } = deps;
const logger = endpointContext.logFactory.get('metadata');
try {
const agentService = endpointContext.service.getAgentService();
if (agentService === undefined) {
if (!agentService) {
throw new Error('agentService not available');
}
const metadataRequestContext = {
esClient,
endpointAppContextService: endpointContext.service,
logger,
savedObjectsClient,
};
const endpointData =
id != null && metadataRequestContext.endpointAppContextService.getAgentService() != null
? await getHostMetaData(metadataRequestContext, id)
: null;
const fleetAgentId = endpointData?.elastic.agent.id;
const [fleetAgentStatus, pendingActions] = !fleetAgentId
? [undefined, {}]
: await Promise.all([
// Get Agent Status
agentService.getAgentStatusById(esClient.asCurrentUser, fleetAgentId),
// Get a list of pending actions (if any)
getPendingActionCounts(
esClient.asCurrentUser,
endpointContext.service.getEndpointMetadataService(),
[fleetAgentId]
).then((results) => {
const endpointData = await endpointContext.service
.getEndpointMetadataService()
// Using `internalUser` ES client below due to the fact that Fleet data has been moved to
// system indices (`.fleet*`). Because this is a readonly action, this should be ok to do
// here until proper RBOC controls are implemented
.getEnrichedHostMetadata(esClient.asInternalUser, id);
const fleetAgentId = endpointData.metadata.elastic.agent.id;
const pendingActions = fleetAgentId
? getPendingActionCounts(
esClient.asInternalUser,
endpointContext.service.getEndpointMetadataService(),
[fleetAgentId]
)
.then((results) => {
return results[0].pending_actions;
}),
]);
})
.catch((error) => {
// Failure in retrieving the number of pending actions should not fail the entire
// call to get endpoint details. Log the error and return an empty object
logger.warn(error);
return {};
})
: {};
return endpointData != null && endpointData
? {
endpointPolicy: endpointData.Endpoint.policy.applied.name,
policyStatus: endpointData.Endpoint.policy.applied.status,
sensorVersion: endpointData.agent.version,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
elasticAgentStatus: fleetAgentStatusToEndpointHostStatus(fleetAgentStatus!),
isolation: endpointData.Endpoint.state?.isolation ?? false,
pendingActions,
}
: null;
return {
endpointPolicy: endpointData.metadata.Endpoint.policy.applied.name,
policyStatus: endpointData.metadata.Endpoint.policy.applied.status,
sensorVersion: endpointData.metadata.agent.version,
elasticAgentStatus: endpointData.host_status,
isolation: endpointData.metadata.Endpoint.state?.isolation ?? false,
pendingActions,
};
} catch (err) {
logger.warn(err);
return null;