mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Synthetics] Filters tls certs by saved objects (#160113)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
b20ccb25a8
commit
79d8349eaf
18 changed files with 250 additions and 63 deletions
|
@ -39,6 +39,8 @@ export enum SYNTHETICS_API_URLS {
|
|||
DELETE_PACKAGE_POLICY = `/internal/synthetics/monitor/policy/{packagePolicyId}`,
|
||||
FILTERS = '/internal/synthetics/monitor/filters',
|
||||
|
||||
CERTS = '/internal/synthetics/certs',
|
||||
|
||||
// Project monitor public endpoint
|
||||
SYNTHETICS_MONITORS_PROJECT = '/api/synthetics/project/{projectName}/monitors',
|
||||
SYNTHETICS_MONITORS_PROJECT_UPDATE = '/api/synthetics/project/{projectName}/monitors/_bulk_update',
|
||||
|
|
|
@ -47,7 +47,7 @@ export const getCertsRequestBody = ({
|
|||
|
||||
const searchRequest = createEsQuery({
|
||||
body: {
|
||||
from: pageIndex * size,
|
||||
from: (pageIndex ?? 0) * size,
|
||||
size,
|
||||
sort: asMutableArray([
|
||||
{
|
||||
|
|
|
@ -7,23 +7,19 @@
|
|||
|
||||
import * as t from 'io-ts';
|
||||
|
||||
export const GetCertsParamsType = t.intersection([
|
||||
t.type({
|
||||
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,
|
||||
filters: t.unknown,
|
||||
monitorIds: t.array(t.string),
|
||||
}),
|
||||
]);
|
||||
export const GetCertsParamsType = t.partial({
|
||||
pageIndex: t.number,
|
||||
search: t.string,
|
||||
notValidBefore: t.string,
|
||||
notValidAfter: t.string,
|
||||
from: t.string,
|
||||
to: t.string,
|
||||
sortBy: t.string,
|
||||
direction: t.string,
|
||||
size: t.number,
|
||||
filters: t.unknown,
|
||||
monitorIds: t.array(t.string),
|
||||
});
|
||||
|
||||
export type GetCertsParams = t.TypeOf<typeof GetCertsParamsType>;
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ const getPageSizeValue = () => {
|
|||
};
|
||||
|
||||
export const CertificatesPage: React.FC = () => {
|
||||
useTrackPageview({ app: 'uptime', path: 'certificates' });
|
||||
useTrackPageview({ app: 'uptime', path: 'certificates', delay: 15000 });
|
||||
useTrackPageview({ app: 'synthetics', path: 'certificates' });
|
||||
useTrackPageview({ app: 'synthetics', path: 'certificates', delay: 15000 });
|
||||
|
||||
useBreadcrumbs([{ text: 'Certificates' }]);
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ describe('CertificateList', () => {
|
|||
page={page}
|
||||
sort={sort}
|
||||
onChange={jest.fn()}
|
||||
certificates={{ loading: false, total: 0, certs: [] }}
|
||||
certificates={{ isLoading: false, total: 0, certs: [] }}
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -48,7 +48,7 @@ describe('CertificateList', () => {
|
|||
sort={sort}
|
||||
onChange={jest.fn()}
|
||||
certificates={{
|
||||
loading: false,
|
||||
isLoading: false,
|
||||
total: 1,
|
||||
certs: [
|
||||
{
|
||||
|
|
|
@ -42,7 +42,7 @@ interface Props {
|
|||
page: Page;
|
||||
sort: CertSort;
|
||||
onChange: (page: Page, sort: CertSort) => void;
|
||||
certificates: CertResult & { loading?: boolean };
|
||||
certificates: CertResult & { isLoading?: boolean };
|
||||
}
|
||||
|
||||
export const CertificateList: React.FC<Props> = ({ page, certificates, sort, onChange }) => {
|
||||
|
@ -101,7 +101,7 @@ export const CertificateList: React.FC<Props> = ({ page, certificates, sort, onC
|
|||
|
||||
return (
|
||||
<EuiBasicTable
|
||||
loading={certificates.loading}
|
||||
loading={certificates.isLoading}
|
||||
columns={columns}
|
||||
items={certificates?.certs ?? []}
|
||||
pagination={pagination}
|
||||
|
@ -113,7 +113,7 @@ export const CertificateList: React.FC<Props> = ({ page, certificates, sort, onC
|
|||
},
|
||||
}}
|
||||
noItemsMessage={
|
||||
certificates.loading ? (
|
||||
certificates.isLoading ? (
|
||||
LOADING_CERTIFICATES
|
||||
) : (
|
||||
<span data-test-subj="uptimeCertsEmptyMessage">{NO_CERTS_AVAILABLE}</span>
|
||||
|
|
|
@ -5,20 +5,16 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useContext } from 'react';
|
||||
import { createEsParams, useEsSearch } from '@kbn/observability-shared-plugin/public';
|
||||
import { useContext, useEffect } from 'react';
|
||||
|
||||
import { SYNTHETICS_INDEX_PATTERN } from '../../../../../common/constants';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { getCertsListAction, selectCertsListState } from '../../state/certs';
|
||||
import {
|
||||
DEFAULT_DIRECTION,
|
||||
DEFAULT_FROM,
|
||||
DEFAULT_SIZE,
|
||||
DEFAULT_SORT,
|
||||
DEFAULT_TO,
|
||||
getCertsRequestBody,
|
||||
processCertsResult,
|
||||
} from '../../../../../common/requests/get_certs_request_body';
|
||||
import { CertResult, GetCertsParams, Ping } from '../../../../../common/runtime_types';
|
||||
import { CertResult, GetCertsParams } from '../../../../../common/runtime_types';
|
||||
import { SyntheticsRefreshContext } from '../../contexts';
|
||||
|
||||
export const useCertSearch = ({
|
||||
|
@ -27,31 +23,24 @@ export const useCertSearch = ({
|
|||
search,
|
||||
sortBy = DEFAULT_SORT,
|
||||
direction = DEFAULT_DIRECTION,
|
||||
}: GetCertsParams): CertResult & { loading?: boolean } => {
|
||||
}: GetCertsParams): CertResult & { isLoading?: boolean } => {
|
||||
const { lastRefresh } = useContext(SyntheticsRefreshContext);
|
||||
|
||||
const searchBody = getCertsRequestBody({
|
||||
pageIndex,
|
||||
size,
|
||||
search,
|
||||
sortBy,
|
||||
direction,
|
||||
to: DEFAULT_TO,
|
||||
from: DEFAULT_FROM,
|
||||
});
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const esParams = createEsParams({
|
||||
index: SYNTHETICS_INDEX_PATTERN,
|
||||
body: searchBody,
|
||||
});
|
||||
useEffect(() => {
|
||||
dispatch(
|
||||
getCertsListAction.get({
|
||||
pageIndex,
|
||||
size,
|
||||
search,
|
||||
sortBy,
|
||||
direction,
|
||||
})
|
||||
);
|
||||
}, [direction, dispatch, lastRefresh, pageIndex, search, size, sortBy]);
|
||||
|
||||
const { data: result, loading } = useEsSearch<Ping, typeof esParams>(
|
||||
esParams,
|
||||
[size, pageIndex, lastRefresh, search, sortBy, direction],
|
||||
{
|
||||
name: 'getTLSCertificates',
|
||||
}
|
||||
);
|
||||
const { data, isLoading } = useSelector(selectCertsListState);
|
||||
|
||||
return result ? { ...processCertsResult(result), loading } : { certs: [], total: 0, loading };
|
||||
return { ...(data ?? { certs: [], total: 0 }), isLoading };
|
||||
};
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* 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 { CertResult, GetCertsParams } from '../../../../../common/runtime_types';
|
||||
import { createAsyncAction } from '../utils/actions';
|
||||
|
||||
export const getCertsListAction = createAsyncAction<GetCertsParams, CertResult>('GET CERTS LIST');
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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 { SYNTHETICS_API_URLS } from '../../../../../common/constants';
|
||||
import { CertResult, GetCertsParams } from '../../../../../common/runtime_types';
|
||||
import { apiService } from '../../../../utils/api_service/api_service';
|
||||
|
||||
export const getCertsList = async (queryParams: GetCertsParams): Promise<CertResult> => {
|
||||
const { pageIndex, size, search, sortBy, direction } = queryParams;
|
||||
const result = (await apiService.get(SYNTHETICS_API_URLS.CERTS, {
|
||||
pageIndex,
|
||||
size,
|
||||
search,
|
||||
sortBy,
|
||||
direction,
|
||||
})) as {
|
||||
data: CertResult;
|
||||
};
|
||||
return result.data;
|
||||
};
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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 { takeLeading } from 'redux-saga/effects';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { fetchEffectFactory } from '../utils/fetch_effect';
|
||||
import { getCertsList } from './api';
|
||||
import { getCertsListAction } from './actions';
|
||||
|
||||
export function* getCertsListEffect() {
|
||||
yield takeLeading(
|
||||
getCertsListAction.get,
|
||||
fetchEffectFactory(
|
||||
getCertsList,
|
||||
getCertsListAction.success,
|
||||
getCertsListAction.fail,
|
||||
undefined,
|
||||
getFailMessage
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const getFailMessage = i18n.translate('xpack.synthetics.getCerts.failed', {
|
||||
defaultMessage: 'Failed to get TLS certificates.',
|
||||
});
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 { createReducer } from '@reduxjs/toolkit';
|
||||
import { CertResult, SyntheticsParamSO } from '../../../../../common/runtime_types';
|
||||
import { IHttpSerializedFetchError } from '..';
|
||||
import { getCertsListAction } from './actions';
|
||||
|
||||
export interface CertsListState {
|
||||
isLoading?: boolean;
|
||||
data?: CertResult;
|
||||
error: IHttpSerializedFetchError | null;
|
||||
isSaving?: boolean;
|
||||
savedData?: SyntheticsParamSO;
|
||||
}
|
||||
|
||||
const initialState: CertsListState = {
|
||||
isLoading: false,
|
||||
error: null,
|
||||
data: { certs: [], total: 0 },
|
||||
};
|
||||
|
||||
export const certsListReducer = createReducer(initialState, (builder) => {
|
||||
builder
|
||||
.addCase(getCertsListAction.get, (state) => {
|
||||
state.isLoading = true;
|
||||
})
|
||||
.addCase(getCertsListAction.success, (state, action) => {
|
||||
state.isLoading = false;
|
||||
state.data = action.payload;
|
||||
})
|
||||
.addCase(getCertsListAction.fail, (state, action) => {
|
||||
state.isLoading = false;
|
||||
state.error = action.payload;
|
||||
});
|
||||
});
|
||||
|
||||
export * from './actions';
|
||||
export * from './effects';
|
||||
export * from './selectors';
|
||||
export * from './api';
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* 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 { AppState } from '..';
|
||||
|
||||
export const selectCertsListState = (state: AppState) => state.certsList;
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import { all, fork } from 'redux-saga/effects';
|
||||
import { getCertsListEffect } from './certs';
|
||||
import { addGlobalParamEffect, editGlobalParamEffect, getGlobalParamEffect } from './global_params';
|
||||
import { fetchManualTestRunsEffect } from './manual_test_runs/effects';
|
||||
import { enableDefaultAlertingEffect, updateDefaultAlertingEffect } from './alert_rules/effects';
|
||||
|
@ -61,5 +62,6 @@ export const rootEffect = function* root(): Generator {
|
|||
fork(addGlobalParamEffect),
|
||||
fork(editGlobalParamEffect),
|
||||
fork(getGlobalParamEffect),
|
||||
fork(getCertsListEffect),
|
||||
]);
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { combineReducers } from '@reduxjs/toolkit';
|
||||
|
||||
import { certsListReducer, CertsListState } from './certs';
|
||||
import { certificatesReducer, CertificatesState } from './certificates/certificates';
|
||||
import { globalParamsReducer, GlobalParamsState } from './global_params';
|
||||
import { overviewStatusReducer, OverviewStatusStateReducer } from './overview_status';
|
||||
|
@ -45,6 +46,7 @@ export interface SyntheticsAppState {
|
|||
manualTestRuns: ManualTestRunsState;
|
||||
monitorDetails: MonitorDetailsState;
|
||||
browserJourney: BrowserJourneyState;
|
||||
certsList: CertsListState;
|
||||
defaultAlerting: DefaultAlertingState;
|
||||
dynamicSettings: DynamicSettingsState;
|
||||
serviceLocations: ServiceLocationsState;
|
||||
|
@ -71,4 +73,5 @@ export const rootReducer = combineReducers<SyntheticsAppState>({
|
|||
serviceLocations: serviceLocationsReducer,
|
||||
syntheticsEnablement: syntheticsEnablementReducer,
|
||||
certificates: certificatesReducer,
|
||||
certsList: certsListReducer,
|
||||
});
|
||||
|
|
|
@ -156,6 +156,13 @@ export const mockState: SyntheticsAppState = {
|
|||
certificates: {
|
||||
total: 0,
|
||||
},
|
||||
certsList: {
|
||||
error: null,
|
||||
data: {
|
||||
total: 0,
|
||||
certs: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function getBrowserJourneyMockSlice() {
|
||||
|
|
|
@ -71,9 +71,10 @@ export type UptimeRoute<ClientContract = unknown> = UMRouteDefinition<
|
|||
export type UMRestApiRouteFactory<ClientContract = unknown> = (
|
||||
libs: UMServerLibs
|
||||
) => UptimeRoute<ClientContract>;
|
||||
export type SyntheticsRestApiRouteFactory<ClientContract = any> = (
|
||||
libs: UMServerLibs
|
||||
) => SyntheticsRoute<ClientContract>;
|
||||
export type SyntheticsRestApiRouteFactory<
|
||||
ClientContract = any,
|
||||
QueryParams = Record<string, any>
|
||||
> = (libs: UMServerLibs) => SyntheticsRoute<ClientContract, QueryParams>;
|
||||
export type SyntheticsStreamingRouteFactory = (libs: UMServerLibs) => SyntheticsStreamingRoute;
|
||||
|
||||
/**
|
||||
|
@ -85,9 +86,10 @@ export type UMKibanaRouteWrapper = (
|
|||
server: UptimeServerSetup
|
||||
) => UMKibanaRoute;
|
||||
|
||||
export type SyntheticsRoute<ClientContract = unknown> = UMRouteDefinition<
|
||||
SyntheticsRouteHandler<ClientContract>
|
||||
>;
|
||||
export type SyntheticsRoute<
|
||||
ClientContract = unknown,
|
||||
QueryParams = Record<string, any>
|
||||
> = UMRouteDefinition<SyntheticsRouteHandler<ClientContract, QueryParams>>;
|
||||
export type SyntheticsStreamingRoute = UMRouteDefinition<SyntheticsStreamingRouteHandler>;
|
||||
|
||||
export type SyntheticsRouteWrapper = (
|
||||
|
@ -131,7 +133,7 @@ export interface RouteContext<Query = Record<string, any>> {
|
|||
spaceId: string;
|
||||
}
|
||||
|
||||
export type SyntheticsRouteHandler<ClientContract = unknown> = ({
|
||||
export type SyntheticsRouteHandler<ClientContract = unknown, Query = Record<string, any>> = ({
|
||||
uptimeEsClient,
|
||||
context,
|
||||
request,
|
||||
|
@ -139,7 +141,7 @@ export type SyntheticsRouteHandler<ClientContract = unknown> = ({
|
|||
server,
|
||||
savedObjectsClient,
|
||||
subject: Subject,
|
||||
}: RouteContext) => Promise<IKibanaResponse<ClientContract> | ClientContract>;
|
||||
}: RouteContext<Query>) => Promise<IKibanaResponse<ClientContract> | ClientContract>;
|
||||
|
||||
export type SyntheticsStreamingRouteHandler = ({
|
||||
uptimeEsClient,
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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 { schema } from '@kbn/config-schema';
|
||||
import {
|
||||
getAllMonitors,
|
||||
processMonitors,
|
||||
} from '../../saved_objects/synthetics_monitor/get_all_monitors';
|
||||
import { monitorAttributes } from '../../../common/types/saved_objects';
|
||||
import { getCerts } from '../../legacy_uptime/lib/requests/get_certs';
|
||||
import { SYNTHETICS_API_URLS } from '../../../common/constants';
|
||||
import { CertResult, GetCertsParams } from '../../../common/runtime_types';
|
||||
import { SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes';
|
||||
import { AlertConfigKey } from '../../../common/constants/monitor_management';
|
||||
|
||||
export const getSyntheticsCertsRoute: SyntheticsRestApiRouteFactory<
|
||||
{ data: CertResult },
|
||||
GetCertsParams
|
||||
> = () => ({
|
||||
method: 'GET',
|
||||
path: SYNTHETICS_API_URLS.CERTS,
|
||||
validate: {
|
||||
query: schema.object({
|
||||
pageIndex: schema.maybe(schema.number()),
|
||||
size: schema.maybe(schema.number()),
|
||||
sortBy: schema.maybe(schema.string()),
|
||||
direction: schema.maybe(schema.string()),
|
||||
search: schema.maybe(schema.string()),
|
||||
from: schema.maybe(schema.string()),
|
||||
to: schema.maybe(schema.string()),
|
||||
}),
|
||||
},
|
||||
handler: async ({
|
||||
request,
|
||||
uptimeEsClient,
|
||||
savedObjectsClient,
|
||||
server,
|
||||
syntheticsMonitorClient,
|
||||
}) => {
|
||||
const queryParams = request.query;
|
||||
|
||||
const monitors = await getAllMonitors({
|
||||
soClient: savedObjectsClient,
|
||||
filter: `${monitorAttributes}.${AlertConfigKey.STATUS_ENABLED}: true`,
|
||||
});
|
||||
|
||||
const { enabledMonitorQueryIds } = await processMonitors(
|
||||
monitors,
|
||||
server,
|
||||
savedObjectsClient,
|
||||
syntheticsMonitorClient
|
||||
);
|
||||
|
||||
const data = await getCerts({
|
||||
...queryParams,
|
||||
uptimeEsClient,
|
||||
monitorIds: enabledMonitorQueryIds,
|
||||
});
|
||||
return { data };
|
||||
},
|
||||
});
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { getSyntheticsCertsRoute } from './certs/get_certificates';
|
||||
import { getAgentPoliciesRoute } from './settings/private_locations/get_agent_policies';
|
||||
import { inspectSyntheticsMonitorRoute } from './monitor_cruds/inspect_monitor';
|
||||
import { deletePackagePolicyRoute } from './monitor_cruds/delete_integration';
|
||||
|
@ -102,6 +103,7 @@ export const syntheticsAppRestApiRoutes: SyntheticsRestApiRouteFactory[] = [
|
|||
getSyntheticsFilters,
|
||||
inspectSyntheticsMonitorRoute,
|
||||
getAgentPoliciesRoute,
|
||||
getSyntheticsCertsRoute,
|
||||
];
|
||||
|
||||
export const syntheticsAppStreamingApiRoutes: SyntheticsStreamingRouteFactory[] = [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue