Skip to content

Commit

Permalink
[Uptime] Use async search api for certificates (elastic#111731)
Browse files Browse the repository at this point in the history
  • Loading branch information
shahzad31 authored Sep 15, 2021
1 parent ce2aac3 commit 895747a
Show file tree
Hide file tree
Showing 28 changed files with 433 additions and 435 deletions.
4 changes: 2 additions & 2 deletions x-pack/plugins/observability/public/hooks/use_es_search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { useKibana } from '../../../../../src/plugins/kibana_react/public';
import { isCompleteResponse } from '../../../../../src/plugins/data/common';
import { useFetcher } from './use_fetcher';

export const useEsSearch = <TParams extends estypes.SearchRequest>(
export const useEsSearch = <DocumentSource extends unknown, TParams extends estypes.SearchRequest>(
params: TParams,
fnDeps: any[]
) => {
Expand Down Expand Up @@ -43,7 +43,7 @@ export const useEsSearch = <TParams extends estypes.SearchRequest>(

const { rawResponse } = response as any;

return { data: rawResponse as ESSearchResponse<unknown, TParams>, loading };
return { data: rawResponse as ESSearchResponse<DocumentSource, TParams>, loading };
};

export function createEsParams<T extends estypes.SearchRequest>(params: T): T {
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/observability/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export {

export const LazyAlertsFlyout = lazy(() => import('./pages/alerts/alerts_flyout'));
export { useFetcher, FETCH_STATUS } from './hooks/use_fetcher';
export { useEsSearch, createEsParams } from './hooks/use_es_search';

export * from './typings';

Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/uptime/common/constants/rest_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*/

export enum API_URLS {
CERTS = '/api/uptime/certs',
INDEX_PATTERN = `/api/uptime/index_pattern`,
INDEX_STATUS = '/api/uptime/index_status',
MONITOR_LIST = `/api/uptime/monitor/list`,
Expand Down
183 changes: 183 additions & 0 deletions x-pack/plugins/uptime/common/requests/get_certs_request_body.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/*
* 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 { estypes } from '@elastic/elasticsearch';
import { CertResult, GetCertsParams, Ping } from '../runtime_types';
import { createEsQuery } from '../utils/es_search';

// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { CertificatesResults } from '../../server/lib/requests/get_certs';
import { asMutableArray } from '../utils/as_mutable_array';

enum SortFields {
'issuer' = 'tls.server.x509.issuer.common_name',
'not_after' = 'tls.server.x509.not_after',
'not_before' = 'tls.server.x509.not_before',
'common_name' = 'tls.server.x509.subject.common_name',
}

export const DEFAULT_SORT = 'not_after';
export const DEFAULT_DIRECTION = 'asc';
export const DEFAULT_SIZE = 20;
export const DEFAULT_FROM = 'now-5m';
export const DEFAULT_TO = 'now';

export const getCertsRequestBody = ({
pageIndex,
search,
notValidBefore,
notValidAfter,
size = DEFAULT_SIZE,
to = DEFAULT_TO,
from = DEFAULT_FROM,
sortBy = DEFAULT_SORT,
direction = DEFAULT_DIRECTION,
}: GetCertsParams) => {
const sort = SortFields[sortBy as keyof typeof SortFields];

const searchRequest = createEsQuery({
body: {
from: pageIndex * size,
size,
sort: asMutableArray([
{
[sort]: {
order: direction,
},
},
]),
query: {
bool: {
...(search
? {
minimum_should_match: 1,
should: [
{
multi_match: {
query: escape(search),
type: 'phrase_prefix' as const,
fields: [
'monitor.id.text',
'monitor.name.text',
'url.full.text',
'tls.server.x509.subject.common_name.text',
'tls.server.x509.issuer.common_name.text',
],
},
},
],
}
: {}),
filter: [
{
exists: {
field: 'tls.server.hash.sha256',
},
},
{
range: {
'monitor.timespan': {
gte: from,
lte: to,
},
},
},
...(notValidBefore
? [
{
range: {
'tls.certificate_not_valid_before': {
lte: notValidBefore,
},
},
},
]
: []),
...(notValidAfter
? [
{
range: {
'tls.certificate_not_valid_after': {
lte: notValidAfter,
},
},
},
]
: []),
] as estypes.QueryDslQueryContainer,
},
},
_source: [
'monitor.id',
'monitor.name',
'tls.server.x509.issuer.common_name',
'tls.server.x509.subject.common_name',
'tls.server.hash.sha1',
'tls.server.hash.sha256',
'tls.server.x509.not_after',
'tls.server.x509.not_before',
],
collapse: {
field: 'tls.server.hash.sha256',
inner_hits: {
_source: {
includes: ['monitor.id', 'monitor.name', 'url.full'],
},
collapse: {
field: 'monitor.id',
},
name: 'monitors',
sort: [{ 'monitor.id': 'asc' as const }],
},
},
aggs: {
total: {
cardinality: {
field: 'tls.server.hash.sha256',
},
},
},
},
});

return searchRequest.body;
};

export const processCertsResult = (result: CertificatesResults): CertResult => {
const certs = result.hits?.hits?.map((hit) => {
const ping = hit._source;
const server = ping.tls?.server!;

const notAfter = server?.x509?.not_after;
const notBefore = server?.x509?.not_before;
const issuer = server?.x509?.issuer?.common_name;
const commonName = server?.x509?.subject?.common_name;
const sha1 = server?.hash?.sha1;
const sha256 = server?.hash?.sha256;

const monitors = hit.inner_hits!.monitors.hits.hits.map((monitor) => {
const monitorPing = monitor._source as Ping;

return {
name: monitorPing?.monitor.name,
id: monitorPing?.monitor.id,
url: monitorPing?.url?.full,
};
});

return {
monitors,
issuer,
sha1,
sha256: sha256 as string,
not_after: notAfter,
not_before: notBefore,
common_name: commonName,
};
});
const total = result.aggregations?.total?.value ?? 0;
return { certs, total };
};
8 changes: 4 additions & 4 deletions x-pack/plugins/uptime/common/runtime_types/certs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ import * as t from 'io-ts';

export const GetCertsParamsType = t.intersection([
t.type({
index: t.number,
size: t.number,
sortBy: t.string,
direction: t.string,
pageIndex: t.number,
}),
t.partial({
search: t.string,
notValidBefore: t.string,
notValidAfter: t.string,
from: t.string,
to: t.string,
sortBy: t.string,
direction: t.string,
size: t.number,
}),
]);

Expand Down
12 changes: 12 additions & 0 deletions x-pack/plugins/uptime/common/utils/es_search.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* 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 { estypes } from '@elastic/elasticsearch';

export function createEsQuery<T extends estypes.SearchRequest>(params: T): T {
return params;
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
* 2.0.
*/

import React, { ChangeEvent } from 'react';
import React, { ChangeEvent, useState } from 'react';
import { EuiFieldSearch } from '@elastic/eui';
import styled from 'styled-components';
import useDebounce from 'react-use/lib/useDebounce';
import * as labels from './translations';

const WrapFieldSearch = styled('div')`
Expand All @@ -19,10 +20,20 @@ interface Props {
}

export const CertificateSearch: React.FC<Props> = ({ setSearch }) => {
const [debouncedValue, setDebouncedValue] = useState('');

const onChange = (e: ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value);
setDebouncedValue(e.target.value);
};

useDebounce(
() => {
setSearch(debouncedValue);
},
350,
[debouncedValue]
);

return (
<WrapFieldSearch>
<EuiFieldSearch
Expand Down
Loading

0 comments on commit 895747a

Please sign in to comment.