mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 10:40:07 -04:00
[Synthetics] Fix tls alert data !! (#212758)
### Summary This PR improves and fixes the TLS alert data handling in the Synthetics plugin. Key updates include: ### Code changes 1. **Request Body Updates**: - Added `agent.name`. - Changed optional chaining to direct property access for `ping.monitor.name`, `ping.monitor.id`, and `ping.observer.name`. - Added `ping.agent.name`. 2. **Cert Type Adjustments**: - Added fields: `monitorName`, `monitorId`, `monitorType`, `locationId`, `locationName`, `@timestamp`, `hostName`. 3. **Observer Codec**: - Ensured `name` and `geo.name` are required fields. 4. **Monitor Type and Ping Type**: - Added `name` to `MonitorType`. - Moved `@timestamp` to required fields in `PingType`. 7. **Message Utils**: - Adjusted `getCertSummary` and `getTLSAlertDocument` so that we can properly generate alert document
This commit is contained in:
parent
a1c520c49d
commit
80f4aab305
13 changed files with 103 additions and 36 deletions
|
@ -138,6 +138,7 @@ export const getCertsRequestBody = ({
|
|||
'monitor.type',
|
||||
'url.full',
|
||||
'observer.geo.name',
|
||||
'agent.name',
|
||||
'tls.server.x509.issuer.common_name',
|
||||
'tls.server.x509.subject.common_name',
|
||||
'tls.server.hash.sha1',
|
||||
|
@ -206,8 +207,8 @@ export const processCertsResult = (result: CertificatesResults): CertResult => {
|
|||
not_after: notAfter,
|
||||
not_before: notBefore,
|
||||
common_name: commonName,
|
||||
monitorName: ping?.monitor?.name,
|
||||
monitorId: ping?.monitor?.id,
|
||||
monitorName: ping.monitor.name,
|
||||
monitorId: ping.monitor.id,
|
||||
serviceName: ping?.service?.name,
|
||||
configId: ping.config_id!,
|
||||
monitorUrl: ping?.url?.full,
|
||||
|
@ -215,7 +216,8 @@ export const processCertsResult = (result: CertificatesResults): CertResult => {
|
|||
tags: ping?.tags,
|
||||
'@timestamp': ping['@timestamp'],
|
||||
monitorType: ping?.monitor?.type,
|
||||
locationId: ping?.observer?.name,
|
||||
locationId: ping.observer.name,
|
||||
hostName: ping?.agent?.name,
|
||||
locationName: ping?.observer?.geo?.name,
|
||||
errorMessage: ping?.error?.message,
|
||||
errorStackTrace: ping?.error?.stack_trace,
|
||||
|
|
|
@ -35,6 +35,12 @@ export const CertType = t.intersection([
|
|||
monitors: t.array(CertMonitorType),
|
||||
sha256: t.string,
|
||||
configId: t.string,
|
||||
monitorName: t.string,
|
||||
monitorId: t.string,
|
||||
monitorType: t.string,
|
||||
locationId: t.string,
|
||||
locationName: t.string,
|
||||
'@timestamp': t.string,
|
||||
}),
|
||||
t.partial({
|
||||
not_after: t.string,
|
||||
|
@ -42,18 +48,14 @@ export const CertType = t.intersection([
|
|||
common_name: t.string,
|
||||
issuer: t.string,
|
||||
sha1: t.string,
|
||||
monitorName: t.string,
|
||||
monitorId: t.string,
|
||||
monitorType: t.string,
|
||||
monitorUrl: t.string,
|
||||
locationId: t.string,
|
||||
locationName: t.string,
|
||||
'@timestamp': t.string,
|
||||
hostName: t.string,
|
||||
serviceName: t.string,
|
||||
errorMessage: t.string,
|
||||
errorStackTrace: t.union([t.string, t.null]),
|
||||
labels: t.record(t.string, t.string),
|
||||
tags: t.array(t.string),
|
||||
monitorTags: t.array(t.string),
|
||||
}),
|
||||
]);
|
||||
|
||||
|
|
|
@ -7,20 +7,28 @@
|
|||
|
||||
import * as t from 'io-ts';
|
||||
|
||||
export const ObserverCodec = t.partial({
|
||||
hostname: t.string,
|
||||
ip: t.array(t.string),
|
||||
mac: t.array(t.string),
|
||||
name: t.union([t.string, t.undefined]),
|
||||
geo: t.partial({
|
||||
export const ObserverCodec = t.intersection([
|
||||
t.type({
|
||||
name: t.string,
|
||||
continent_name: t.string,
|
||||
city_name: t.string,
|
||||
country_iso_code: t.string,
|
||||
location: t.union([
|
||||
t.string,
|
||||
t.partial({ lat: t.number, lon: t.number }),
|
||||
t.partial({ lat: t.string, lon: t.string }),
|
||||
geo: t.intersection([
|
||||
t.type({
|
||||
name: t.string,
|
||||
}),
|
||||
t.partial({
|
||||
continent_name: t.string,
|
||||
city_name: t.string,
|
||||
country_iso_code: t.string,
|
||||
location: t.union([
|
||||
t.string,
|
||||
t.partial({ lat: t.number, lon: t.number }),
|
||||
t.partial({ lat: t.string, lon: t.string }),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
});
|
||||
t.partial({
|
||||
hostname: t.string,
|
||||
ip: t.array(t.string),
|
||||
mac: t.array(t.string),
|
||||
}),
|
||||
]);
|
||||
|
|
|
@ -92,6 +92,7 @@ export type Tls = t.TypeOf<typeof TlsType>;
|
|||
|
||||
export const MonitorType = t.intersection([
|
||||
t.type({
|
||||
name: t.string,
|
||||
id: t.string,
|
||||
status: t.string,
|
||||
type: t.string,
|
||||
|
@ -106,7 +107,6 @@ export const MonitorType = t.intersection([
|
|||
us: t.number,
|
||||
}),
|
||||
ip: t.string,
|
||||
name: t.string,
|
||||
|
||||
fleet_managed: t.boolean,
|
||||
project: t.type({
|
||||
|
@ -163,9 +163,9 @@ export const PingType = t.intersection([
|
|||
monitor: MonitorType,
|
||||
docId: t.string,
|
||||
observer: ObserverCodec,
|
||||
'@timestamp': t.string,
|
||||
}),
|
||||
t.partial({
|
||||
'@timestamp': t.string,
|
||||
agent: AgentType,
|
||||
container: t.partial({
|
||||
id: t.string,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import React from 'react';
|
||||
import { CertificateList, CertSort } from './certificates_list';
|
||||
import { render } from '../../utils/testing';
|
||||
import { Cert } from '../../../../../common/runtime_types';
|
||||
|
||||
describe('CertificateList', () => {
|
||||
it('render empty state', () => {
|
||||
|
@ -66,7 +67,7 @@ describe('CertificateList', () => {
|
|||
not_before: '2015-04-09T00:00:00.000Z',
|
||||
common_name: '*.badssl.com',
|
||||
configId: 'uptime-advanced-http-tls',
|
||||
},
|
||||
} as Cert,
|
||||
],
|
||||
}}
|
||||
/>
|
||||
|
|
|
@ -12,7 +12,7 @@ import { render } from '../../utils/testing';
|
|||
import { Cert } from '../../../../../common/runtime_types';
|
||||
|
||||
describe('FingerprintCol', () => {
|
||||
const cert: Cert = {
|
||||
const cert = {
|
||||
monitors: [{ name: '', id: 'github', url: 'https://github.com/' }],
|
||||
not_after: '2020-05-08T00:00:00.000Z',
|
||||
not_before: '2018-05-08T00:00:00.000Z',
|
||||
|
@ -21,7 +21,7 @@ describe('FingerprintCol', () => {
|
|||
sha256: '3111500c4a66012cdae333ec3fca1c9dde45c954440e7ee413716bff3663c074'.toUpperCase(),
|
||||
common_name: 'github.com',
|
||||
configId: '123',
|
||||
};
|
||||
} as Cert;
|
||||
|
||||
it('renders expected elements for valid props', async () => {
|
||||
cert.not_after = moment().add('4', 'months').toISOString();
|
||||
|
|
|
@ -39,6 +39,7 @@ describe('Monitor Detail Flyout', () => {
|
|||
docId: 'docId',
|
||||
timestamp: '2013-03-01 12:54:23',
|
||||
monitor: {
|
||||
name: 'test monitor',
|
||||
id: 'test-id',
|
||||
status: 'up',
|
||||
type: 'http',
|
||||
|
@ -52,7 +53,13 @@ describe('Monitor Detail Flyout', () => {
|
|||
full: 'https://www.elastic.co',
|
||||
},
|
||||
tags: ['tag1', 'tag2'],
|
||||
observer: {},
|
||||
observer: {
|
||||
name: 'us-east-1',
|
||||
geo: {
|
||||
name: 'US East',
|
||||
},
|
||||
},
|
||||
'@timestamp': '2013-03-01 12:54:23',
|
||||
},
|
||||
});
|
||||
jest.spyOn(statusByLocation, 'useStatusByLocation').mockReturnValue({
|
||||
|
|
|
@ -50,7 +50,7 @@ export const initTlsAlertType: AlertTypeInitializer = ({
|
|||
},
|
||||
defaultActionMessage,
|
||||
defaultRecoveryMessage,
|
||||
requiresAppContext: true,
|
||||
requiresAppContext: false,
|
||||
format: ({ fields }) => ({
|
||||
reason: fields[ALERT_REASON] || '',
|
||||
link: `/app/synthetics${CERTIFICATES_ROUTE}`,
|
||||
|
|
|
@ -241,6 +241,7 @@ function getMonitorDetailsMockSlice() {
|
|||
full: 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
|
||||
},
|
||||
observer: {
|
||||
name: 'us-central',
|
||||
geo: {
|
||||
continent_name: 'North America',
|
||||
city_name: 'Iowa',
|
||||
|
@ -307,6 +308,7 @@ function getMonitorDetailsMockSlice() {
|
|||
full: 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
|
||||
},
|
||||
observer: {
|
||||
name: 'us-central',
|
||||
geo: {
|
||||
continent_name: 'North America',
|
||||
city_name: 'Iowa',
|
||||
|
@ -362,6 +364,7 @@ function getMonitorDetailsMockSlice() {
|
|||
full: 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
|
||||
},
|
||||
observer: {
|
||||
name: 'us-central',
|
||||
geo: {
|
||||
continent_name: 'North America',
|
||||
city_name: 'Iowa',
|
||||
|
@ -417,6 +420,7 @@ function getMonitorDetailsMockSlice() {
|
|||
full: 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
|
||||
},
|
||||
observer: {
|
||||
name: 'us-central',
|
||||
geo: {
|
||||
continent_name: 'North America',
|
||||
city_name: 'Iowa',
|
||||
|
|
|
@ -16,6 +16,7 @@ describe('setTLSRecoveredAlertsContext', () => {
|
|||
const basePath = {
|
||||
publicBaseUrl: 'https://localhost:5601',
|
||||
} as IBasePath;
|
||||
|
||||
const alertState = {
|
||||
summary: 'test-summary',
|
||||
status: 'has expired',
|
||||
|
|
|
@ -17,12 +17,14 @@ import { i18n } from '@kbn/i18n';
|
|||
import { PublicAlertsClient } from '@kbn/alerting-plugin/server/alerts_client/types';
|
||||
import { ObservabilityUptimeAlert } from '@kbn/alerts-as-data-utils';
|
||||
import { ALERT_REASON, ALERT_UUID } from '@kbn/rule-data-utils';
|
||||
import { MonitorSummaryTLSRule } from './types';
|
||||
import { TLSLatestPing } from './tls_rule_executor';
|
||||
import { ALERT_DETAILS_URL } from '../action_variables';
|
||||
import { Cert } from '../../../common/runtime_types';
|
||||
import { tlsTranslations } from '../translations';
|
||||
import { MonitorStatusActionGroup } from '../../../common/constants/synthetics_alerts';
|
||||
import {
|
||||
AGENT_NAME,
|
||||
CERT_COMMON_NAME,
|
||||
CERT_HASH_SHA256,
|
||||
CERT_ISSUER_NAME,
|
||||
|
@ -76,7 +78,11 @@ const getValidAfter = (notAfter?: string): TLSContent => {
|
|||
|
||||
export type CertSummary = ReturnType<typeof getCertSummary>;
|
||||
|
||||
export const getCertSummary = (cert: Cert, expirationThreshold: number, ageThreshold: number) => {
|
||||
export const getCertSummary = (
|
||||
cert: Cert,
|
||||
expirationThreshold: number,
|
||||
ageThreshold: number
|
||||
): MonitorSummaryTLSRule => {
|
||||
const isExpiring = new Date(cert.not_after ?? '').valueOf() < expirationThreshold;
|
||||
const isAging = new Date(cert.not_before ?? '').valueOf() < ageThreshold;
|
||||
let content: TLSContent | null = null;
|
||||
|
@ -103,9 +109,12 @@ export const getCertSummary = (cert: Cert, expirationThreshold: number, ageThres
|
|||
monitorUrl: cert.monitorUrl,
|
||||
configId: cert.configId,
|
||||
monitorTags: cert.tags,
|
||||
errorMessage: cert.errorMessage,
|
||||
errorStackTrace: cert.errorStackTrace,
|
||||
lastErrorMessage: cert.errorMessage,
|
||||
lastErrorStack: cert.errorStackTrace,
|
||||
labels: cert.labels,
|
||||
reason: summary,
|
||||
hostName: cert.hostName,
|
||||
checkedAt: cert['@timestamp'],
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -124,9 +133,10 @@ export const getTLSAlertDocument = (cert: Cert, monitorSummary: CertSummary, uui
|
|||
[URL_FULL]: monitorSummary.monitorUrl,
|
||||
[OBSERVER_GEO_NAME]: monitorSummary.locationName ? [monitorSummary.locationName] : [],
|
||||
[OBSERVER_NAME]: monitorSummary.locationId ? [monitorSummary.locationId] : [],
|
||||
[ERROR_MESSAGE]: monitorSummary.errorMessage,
|
||||
[ERROR_MESSAGE]: monitorSummary.lastErrorMessage,
|
||||
[AGENT_NAME]: monitorSummary.hostName,
|
||||
// done to avoid assigning null to the field
|
||||
[ERROR_STACK_TRACE]: monitorSummary.errorStackTrace ? monitorSummary.errorStackTrace : undefined,
|
||||
[ERROR_STACK_TRACE]: monitorSummary.lastErrorStack ? monitorSummary.lastErrorStack : undefined,
|
||||
'location.id': monitorSummary.locationId ? [monitorSummary.locationId] : [],
|
||||
'location.name': monitorSummary.locationName ? [monitorSummary.locationName] : [],
|
||||
labels: cert.labels,
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export interface MonitorSummaryTLSRule {
|
||||
reason: string;
|
||||
summary: string;
|
||||
status: string;
|
||||
configId: string;
|
||||
hostName?: string;
|
||||
monitorId: string;
|
||||
checkedAt: string;
|
||||
monitorUrl?: string;
|
||||
locationId: string;
|
||||
monitorType: string;
|
||||
monitorName: string;
|
||||
serviceName?: string;
|
||||
locationName: string;
|
||||
lastErrorMessage?: string;
|
||||
lastErrorStack?: string | null;
|
||||
stateId?: string | null;
|
||||
monitorUrlLabel?: string;
|
||||
sha256: string;
|
||||
commonName: string;
|
||||
issuer: string;
|
||||
monitorTags?: string[];
|
||||
labels?: Record<string, string>;
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { MonitorSummaryTLSRule } from './tls_rule/types';
|
||||
import { MonitorSummaryStatusRule } from './status_rule/types';
|
||||
|
||||
export const STATUS_RULE_NAME = i18n.translate('xpack.synthetics.alertRules.monitorStatus', {
|
||||
|
@ -13,7 +14,7 @@ export const STATUS_RULE_NAME = i18n.translate('xpack.synthetics.alertRules.moni
|
|||
});
|
||||
|
||||
export const commonMonitorStateI18: Array<{
|
||||
name: keyof MonitorSummaryStatusRule;
|
||||
name: keyof MonitorSummaryStatusRule | keyof MonitorSummaryTLSRule;
|
||||
description: string;
|
||||
}> = [
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue