mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Synthetics] enable/disable - prevent incorrect keys from being added to the monitor saved object (#140553)
* synthetics - enable/disable - prevent incorrect keys from being added to the monitor saved object * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * adjust types * add exact typing * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * adjust test * use exact types * use exact types for editing * adjust types * adjust tests * adjust types * Update x-pack/test/api_integration/apis/uptime/rest/add_monitor.ts * adjust normalizers * Update x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types.ts * Update x-pack/plugins/synthetics/server/routes/monitor_cruds/add_monitor.ts * adjust types * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * adjust jest tests * adjust types * adjust api_integration tests * update tests Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
49d0858a40
commit
27916d316a
37 changed files with 339 additions and 103 deletions
|
@ -108,6 +108,7 @@ export const DEFAULT_HTTP_SIMPLE_FIELDS: HTTPSimpleFields = {
|
|||
[ConfigKey.MAX_REDIRECTS]: '0',
|
||||
[ConfigKey.MONITOR_TYPE]: DataStream.HTTP,
|
||||
[ConfigKey.FORM_MONITOR_TYPE]: FormMonitorType.HTTP,
|
||||
[ConfigKey.PORT]: null,
|
||||
};
|
||||
|
||||
export const DEFAULT_HTTP_ADVANCED_FIELDS: HTTPAdvancedFields = {
|
||||
|
@ -144,6 +145,7 @@ export const DEFAULT_TCP_SIMPLE_FIELDS: TCPSimpleFields = {
|
|||
[ConfigKey.HOSTS]: '',
|
||||
[ConfigKey.MONITOR_TYPE]: DataStream.TCP,
|
||||
[ConfigKey.FORM_MONITOR_TYPE]: FormMonitorType.TCP,
|
||||
[ConfigKey.PORT]: null,
|
||||
};
|
||||
|
||||
export const DEFAULT_TCP_ADVANCED_FIELDS: TCPAdvancedFields = {
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
tlsValueToStringFormatter,
|
||||
tlsArrayToYamlFormatter,
|
||||
} from '../tls/formatters';
|
||||
import { tlsFormatters } from '../tls/formatters';
|
||||
|
||||
export type BrowserFormatMap = Record<keyof BrowserFields, Formatter>;
|
||||
|
||||
|
@ -72,9 +73,8 @@ export const browserFormatters: BrowserFormatMap = {
|
|||
arrayToJsonFormatter(fields[ConfigKey.JOURNEY_FILTERS_TAGS]),
|
||||
[ConfigKey.THROTTLING_CONFIG]: throttlingFormatter,
|
||||
[ConfigKey.IGNORE_HTTPS_ERRORS]: null,
|
||||
[ConfigKey.PROJECT_ID]: null,
|
||||
[ConfigKey.PLAYWRIGHT_OPTIONS]: null,
|
||||
[ConfigKey.ORIGINAL_SPACE]: null,
|
||||
[ConfigKey.TEXT_ASSERTION]: null,
|
||||
...commonFormatters,
|
||||
...tlsFormatters,
|
||||
};
|
||||
|
|
|
@ -29,7 +29,9 @@ export const commonFormatters: CommonFormatMap = {
|
|||
[ConfigKey.MONITOR_SOURCE_TYPE]: null,
|
||||
[ConfigKey.FORM_MONITOR_TYPE]: null,
|
||||
[ConfigKey.JOURNEY_ID]: null,
|
||||
[ConfigKey.PROJECT_ID]: null,
|
||||
[ConfigKey.CUSTOM_HEARTBEAT_ID]: null,
|
||||
[ConfigKey.ORIGINAL_SPACE]: null,
|
||||
};
|
||||
|
||||
export const arrayToJsonFormatter = (value: string[] = []) =>
|
||||
|
|
|
@ -41,6 +41,7 @@ export const httpFormatters: HTTPFormatMap = {
|
|||
[ConfigKey.REQUEST_HEADERS_CHECK]: (fields) =>
|
||||
objectToJsonFormatter(fields[ConfigKey.REQUEST_HEADERS_CHECK]),
|
||||
[ConfigKey.REQUEST_METHOD_CHECK]: null,
|
||||
[ConfigKey.PORT]: null,
|
||||
...tlsFormatters,
|
||||
...commonFormatters,
|
||||
};
|
||||
|
|
|
@ -19,6 +19,7 @@ export const tcpFormatters: TCPFormatMap = {
|
|||
[ConfigKey.PROXY_USE_LOCAL_RESOLVER]: null,
|
||||
[ConfigKey.RESPONSE_RECEIVE_CHECK]: null,
|
||||
[ConfigKey.REQUEST_SEND_CHECK]: null,
|
||||
[ConfigKey.PORT]: null,
|
||||
...tlsFormatters,
|
||||
...commonFormatters,
|
||||
};
|
||||
|
|
|
@ -83,6 +83,8 @@ export const CommonFieldsCodec = t.intersection([
|
|||
[ConfigKey.MONITOR_SOURCE_TYPE]: SourceTypeCodec,
|
||||
[ConfigKey.CONFIG_ID]: t.string,
|
||||
[ConfigKey.JOURNEY_ID]: t.string,
|
||||
[ConfigKey.PROJECT_ID]: t.string,
|
||||
[ConfigKey.ORIGINAL_SPACE]: t.string,
|
||||
[ConfigKey.CUSTOM_HEARTBEAT_ID]: t.string,
|
||||
}),
|
||||
]);
|
||||
|
@ -94,6 +96,7 @@ export const TCPSimpleFieldsCodec = t.intersection([
|
|||
t.interface({
|
||||
[ConfigKey.METADATA]: MetadataCodec,
|
||||
[ConfigKey.HOSTS]: t.string,
|
||||
[ConfigKey.PORT]: t.union([t.number, t.null]),
|
||||
}),
|
||||
CommonFieldsCodec,
|
||||
]);
|
||||
|
@ -151,6 +154,7 @@ export const HTTPSimpleFieldsCodec = t.intersection([
|
|||
[ConfigKey.METADATA]: MetadataCodec,
|
||||
[ConfigKey.MAX_REDIRECTS]: t.string,
|
||||
[ConfigKey.URLS]: t.string,
|
||||
[ConfigKey.PORT]: t.union([t.number, t.null]),
|
||||
}),
|
||||
CommonFieldsCodec,
|
||||
]);
|
||||
|
@ -217,8 +221,6 @@ export const EncryptedBrowserSimpleFieldsCodec = t.intersection([
|
|||
}),
|
||||
t.partial({
|
||||
[ConfigKey.PLAYWRIGHT_OPTIONS]: t.string,
|
||||
[ConfigKey.PROJECT_ID]: t.string,
|
||||
[ConfigKey.ORIGINAL_SPACE]: t.string,
|
||||
[ConfigKey.TEXT_ASSERTION]: t.string,
|
||||
}),
|
||||
]),
|
||||
|
@ -241,7 +243,7 @@ export const BrowserSensitiveSimpleFieldsCodec = t.intersection([
|
|||
CommonFieldsCodec,
|
||||
]);
|
||||
|
||||
export const BrowserAdvancedFieldsCodec = t.interface({
|
||||
export const EncryptedBrowserAdvancedFieldsCodec = t.interface({
|
||||
[ConfigKey.SCREENSHOTS]: t.string,
|
||||
[ConfigKey.JOURNEY_FILTERS_MATCH]: t.string,
|
||||
[ConfigKey.JOURNEY_FILTERS_TAGS]: t.array(t.string),
|
||||
|
@ -263,25 +265,26 @@ export const BrowserSensitiveAdvancedFieldsCodec = t.interface({
|
|||
[ConfigKey.SYNTHETICS_ARGS]: t.array(t.string),
|
||||
});
|
||||
|
||||
export const BrowserAdvancedsCodec = t.intersection([
|
||||
BrowserAdvancedFieldsCodec,
|
||||
export const BrowserAdvancedFieldsCodec = t.intersection([
|
||||
EncryptedBrowserAdvancedFieldsCodec,
|
||||
BrowserSensitiveAdvancedFieldsCodec,
|
||||
]);
|
||||
|
||||
export const EncryptedBrowserFieldsCodec = t.intersection([
|
||||
EncryptedBrowserSimpleFieldsCodec,
|
||||
BrowserAdvancedFieldsCodec,
|
||||
EncryptedBrowserAdvancedFieldsCodec,
|
||||
TLSFieldsCodec,
|
||||
]);
|
||||
|
||||
export const BrowserFieldsCodec = t.intersection([
|
||||
BrowserSimpleFieldsCodec,
|
||||
BrowserAdvancedFieldsCodec,
|
||||
BrowserSensitiveAdvancedFieldsCodec,
|
||||
TLSCodec,
|
||||
]);
|
||||
|
||||
export type BrowserFields = t.TypeOf<typeof BrowserFieldsCodec>;
|
||||
export type BrowserSimpleFields = t.TypeOf<typeof BrowserSimpleFieldsCodec>;
|
||||
export type BrowserAdvancedFields = t.TypeOf<typeof BrowserAdvancedsCodec>;
|
||||
export type BrowserAdvancedFields = t.TypeOf<typeof BrowserAdvancedFieldsCodec>;
|
||||
|
||||
// MonitorFields, represents any possible monitor type
|
||||
export const MonitorFieldsCodec = t.intersection([
|
||||
|
|
|
@ -134,6 +134,7 @@ describe('format', () => {
|
|||
timeout: '16',
|
||||
type: 'http',
|
||||
urls: 'sample url',
|
||||
'url.port': null,
|
||||
username: '',
|
||||
});
|
||||
});
|
||||
|
@ -347,6 +348,7 @@ describe('format', () => {
|
|||
timeout: '16',
|
||||
type: 'http',
|
||||
urls: 'sample url',
|
||||
'url.port': null,
|
||||
username: '',
|
||||
});
|
||||
});
|
||||
|
|
|
@ -51,7 +51,7 @@ export const MonitorEnabled = ({
|
|||
|
||||
const handleEnabledChange = (event: EuiSwitchEvent) => {
|
||||
const checked = event.target.checked;
|
||||
updateMonitorEnabledState(monitor, checked);
|
||||
updateMonitorEnabledState(checked);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -111,15 +111,7 @@ describe('ActionsPopover', () => {
|
|||
const enableButton = getByText('Disable monitor');
|
||||
fireEvent.click(enableButton);
|
||||
expect(updateMonitorEnabledState).toHaveBeenCalledTimes(1);
|
||||
expect(updateMonitorEnabledState.mock.calls[0]).toEqual([
|
||||
{
|
||||
id: 'somelongstring',
|
||||
isEnabled: true,
|
||||
location: { id: 'us_central', isServiceManaged: true },
|
||||
name: 'Monitor 1',
|
||||
},
|
||||
false,
|
||||
]);
|
||||
expect(updateMonitorEnabledState.mock.calls[0]).toEqual([false]);
|
||||
});
|
||||
|
||||
it('sets enabled state to true', async () => {
|
||||
|
@ -139,14 +131,6 @@ describe('ActionsPopover', () => {
|
|||
const enableButton = getByText('Enable monitor');
|
||||
fireEvent.click(enableButton);
|
||||
expect(updateMonitorEnabledState).toHaveBeenCalledTimes(1);
|
||||
expect(updateMonitorEnabledState.mock.calls[0]).toEqual([
|
||||
{
|
||||
id: 'somelongstring',
|
||||
isEnabled: false,
|
||||
location: { id: 'us_central', isServiceManaged: true },
|
||||
name: 'Monitor 1',
|
||||
},
|
||||
true,
|
||||
]);
|
||||
expect(updateMonitorEnabledState.mock.calls[0]).toEqual([true]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -141,7 +141,7 @@ export function ActionsPopover({
|
|||
icon: 'invert',
|
||||
onClick: () => {
|
||||
if (status !== FETCH_STATUS.LOADING)
|
||||
updateMonitorEnabledState(monitor, !monitor.isEnabled);
|
||||
updateMonitorEnabledState(!monitor.isEnabled);
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
@ -9,11 +9,7 @@ import { useKibana } from '@kbn/kibana-react-plugin/public';
|
|||
import { FETCH_STATUS } from '@kbn/observability-plugin/public';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import {
|
||||
ConfigKey,
|
||||
EncryptedSyntheticsMonitor,
|
||||
MonitorOverviewItem,
|
||||
} from '../components/monitors_page/overview/types';
|
||||
import { ConfigKey } from '../components/monitors_page/overview/types';
|
||||
import {
|
||||
clearMonitorUpsertStatus,
|
||||
fetchUpsertMonitorAction,
|
||||
|
@ -41,11 +37,11 @@ export function useMonitorEnableHandler({
|
|||
const savedObjEnabledState = upsertStatuses[id]?.enabled;
|
||||
const [isEnabled, setIsEnabled] = useState<boolean | null>(null);
|
||||
const updateMonitorEnabledState = useCallback(
|
||||
(monitor: EncryptedSyntheticsMonitor | MonitorOverviewItem, enabled: boolean) => {
|
||||
(enabled: boolean) => {
|
||||
dispatch(
|
||||
fetchUpsertMonitorAction({
|
||||
id,
|
||||
monitor: { ...monitor, [ConfigKey.ENABLED]: enabled },
|
||||
monitor: { [ConfigKey.ENABLED]: enabled },
|
||||
})
|
||||
);
|
||||
},
|
||||
|
|
|
@ -10,7 +10,6 @@ import { createAction } from '@reduxjs/toolkit';
|
|||
import {
|
||||
EncryptedSyntheticsMonitor,
|
||||
MonitorManagementListResult,
|
||||
MonitorOverviewItem,
|
||||
} from '../../../../../common/runtime_types';
|
||||
import { createAsyncAction } from '../utils/actions';
|
||||
|
||||
|
@ -23,7 +22,7 @@ export const fetchMonitorListAction = createAsyncAction<
|
|||
|
||||
export interface UpsertMonitorRequest {
|
||||
id: string;
|
||||
monitor: EncryptedSyntheticsMonitor | MonitorOverviewItem;
|
||||
monitor: Partial<EncryptedSyntheticsMonitor>;
|
||||
}
|
||||
export const fetchUpsertMonitorAction = createAction<UpsertMonitorRequest>('fetchUpsertMonitor');
|
||||
export const fetchUpsertSuccessAction = createAction<{
|
||||
|
|
|
@ -11,7 +11,6 @@ import {
|
|||
FetchMonitorManagementListQueryArgs,
|
||||
MonitorManagementListResult,
|
||||
MonitorManagementListResultCodec,
|
||||
MonitorOverviewItem,
|
||||
ServiceLocationErrors,
|
||||
SyntheticsMonitor,
|
||||
} from '../../../../../common/runtime_types';
|
||||
|
@ -55,7 +54,7 @@ export const fetchUpsertMonitor = async ({
|
|||
monitor,
|
||||
id,
|
||||
}: {
|
||||
monitor: SyntheticsMonitor | EncryptedSyntheticsMonitor | MonitorOverviewItem;
|
||||
monitor: Partial<SyntheticsMonitor> | Partial<EncryptedSyntheticsMonitor>;
|
||||
id?: string;
|
||||
}): Promise<{ attributes: { errors: ServiceLocationErrors } } | SyntheticsMonitor> => {
|
||||
if (id) {
|
||||
|
|
|
@ -13,6 +13,8 @@ import {
|
|||
LocationStatus,
|
||||
ScheduleUnit,
|
||||
SourceType,
|
||||
VerificationMode,
|
||||
TLSVersion,
|
||||
} from '../../../../../../common/runtime_types';
|
||||
|
||||
/**
|
||||
|
@ -338,8 +340,8 @@ function getMonitorDetailsMockSlice() {
|
|||
'ssl.certificate': '',
|
||||
'ssl.key': '',
|
||||
'ssl.key_passphrase': '',
|
||||
'ssl.verification_mode': 'full',
|
||||
'ssl.supported_protocols': ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'],
|
||||
'ssl.verification_mode': VerificationMode.FULL,
|
||||
'ssl.supported_protocols': ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'] as TLSVersion[],
|
||||
revision: 1,
|
||||
updated_at: '2022-07-24T17:15:46.342Z',
|
||||
},
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
getNormalizer,
|
||||
getJsonToJavascriptNormalizer,
|
||||
} from '../common/normalizers';
|
||||
import { tlsNormalizers } from '../tls/normalizers';
|
||||
|
||||
import { defaultBrowserSimpleFields, defaultBrowserAdvancedFields } from '../contexts';
|
||||
|
||||
|
@ -107,9 +108,8 @@ export const browserNormalizers: BrowserNormalizerMap = {
|
|||
ConfigKey.JOURNEY_FILTERS_TAGS
|
||||
),
|
||||
[ConfigKey.IGNORE_HTTPS_ERRORS]: getBrowserNormalizer(ConfigKey.IGNORE_HTTPS_ERRORS),
|
||||
[ConfigKey.PROJECT_ID]: getBrowserNormalizer(ConfigKey.PROJECT_ID),
|
||||
[ConfigKey.PLAYWRIGHT_OPTIONS]: getBrowserNormalizer(ConfigKey.PLAYWRIGHT_OPTIONS),
|
||||
[ConfigKey.ORIGINAL_SPACE]: getBrowserNormalizer(ConfigKey.ORIGINAL_SPACE),
|
||||
[ConfigKey.TEXT_ASSERTION]: getBrowserNormalizer(ConfigKey.TEXT_ASSERTION),
|
||||
...commonNormalizers,
|
||||
...tlsNormalizers,
|
||||
};
|
||||
|
|
|
@ -93,5 +93,7 @@ export const commonNormalizers: CommonNormalizerMap = {
|
|||
[ConfigKey.MONITOR_SOURCE_TYPE]: getCommonNormalizer(ConfigKey.MONITOR_SOURCE_TYPE),
|
||||
[ConfigKey.FORM_MONITOR_TYPE]: getCommonNormalizer(ConfigKey.FORM_MONITOR_TYPE),
|
||||
[ConfigKey.JOURNEY_ID]: getCommonNormalizer(ConfigKey.JOURNEY_ID),
|
||||
[ConfigKey.PROJECT_ID]: getCommonNormalizer(ConfigKey.PROJECT_ID),
|
||||
[ConfigKey.CUSTOM_HEARTBEAT_ID]: getCommonNormalizer(ConfigKey.CUSTOM_HEARTBEAT_ID),
|
||||
[ConfigKey.ORIGINAL_SPACE]: getCommonNormalizer(ConfigKey.ORIGINAL_SPACE),
|
||||
};
|
||||
|
|
|
@ -34,6 +34,7 @@ export const getHTTPJsonToJavascriptNormalizer = (key: ConfigKey) => {
|
|||
export const httpNormalizers: HTTPNormalizerMap = {
|
||||
[ConfigKey.METADATA]: getHTTPJsonToJavascriptNormalizer(ConfigKey.METADATA),
|
||||
[ConfigKey.URLS]: getHTTPNormalizer(ConfigKey.URLS),
|
||||
[ConfigKey.PORT]: getHTTPNormalizer(ConfigKey.PORT),
|
||||
[ConfigKey.MAX_REDIRECTS]: getHTTPNormalizer(ConfigKey.MAX_REDIRECTS),
|
||||
[ConfigKey.USERNAME]: getHTTPNormalizer(ConfigKey.USERNAME),
|
||||
[ConfigKey.PASSWORD]: getHTTPNormalizer(ConfigKey.PASSWORD),
|
||||
|
|
|
@ -33,6 +33,7 @@ export const getTCPJsonToJavascriptNormalizer = (key: ConfigKey) => {
|
|||
export const tcpNormalizers: TCPNormalizerMap = {
|
||||
[ConfigKey.METADATA]: getTCPJsonToJavascriptNormalizer(ConfigKey.METADATA),
|
||||
[ConfigKey.HOSTS]: getTCPNormalizer(ConfigKey.HOSTS),
|
||||
[ConfigKey.PORT]: getTCPNormalizer(ConfigKey.PORT),
|
||||
[ConfigKey.PROXY_URL]: getTCPNormalizer(ConfigKey.PROXY_URL),
|
||||
[ConfigKey.PROXY_USE_LOCAL_RESOLVER]: getTCPNormalizer(ConfigKey.PROXY_USE_LOCAL_RESOLVER),
|
||||
[ConfigKey.RESPONSE_RECEIVE_CHECK]: getTCPNormalizer(ConfigKey.RESPONSE_RECEIVE_CHECK),
|
||||
|
|
|
@ -67,7 +67,7 @@ export const addSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () => ({
|
|||
|
||||
const validationResult = validateMonitor(monitorWithDefaults as MonitorFields);
|
||||
|
||||
if (!validationResult.valid) {
|
||||
if (!validationResult.valid || !validationResult.decodedMonitor) {
|
||||
const { reason: message, details, payload } = validationResult;
|
||||
return response.badRequest({ body: { message, attributes: { details, ...payload } } });
|
||||
}
|
||||
|
@ -78,8 +78,7 @@ export const addSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () => ({
|
|||
|
||||
try {
|
||||
const { errors, newMonitor } = await syncNewMonitor({
|
||||
normalizedMonitor: monitorWithDefaults,
|
||||
monitor,
|
||||
normalizedMonitor: validationResult.decodedMonitor,
|
||||
server,
|
||||
syntheticsMonitorClient,
|
||||
savedObjectsClient,
|
||||
|
@ -140,7 +139,6 @@ export const createNewSavedObjectMonitor = async ({
|
|||
|
||||
export const syncNewMonitor = async ({
|
||||
id,
|
||||
monitor,
|
||||
server,
|
||||
syntheticsMonitorClient,
|
||||
savedObjectsClient,
|
||||
|
@ -150,7 +148,6 @@ export const syncNewMonitor = async ({
|
|||
spaceId,
|
||||
}: {
|
||||
id?: string;
|
||||
monitor: SyntheticsMonitor;
|
||||
normalizedMonitor: SyntheticsMonitor;
|
||||
server: UptimeServerSetup;
|
||||
syntheticsMonitorClient: SyntheticsMonitorClient;
|
||||
|
@ -201,7 +198,7 @@ export const syncNewMonitor = async ({
|
|||
formatTelemetryEvent({
|
||||
errors: syncErrors,
|
||||
monitor: monitorSavedObject,
|
||||
isInlineScript: Boolean((monitor as MonitorFields)[ConfigKey.SOURCE_INLINE]),
|
||||
isInlineScript: Boolean((normalizedMonitor as MonitorFields)[ConfigKey.SOURCE_INLINE]),
|
||||
kibanaVersion: server.kibanaVersion,
|
||||
})
|
||||
);
|
||||
|
|
|
@ -84,13 +84,13 @@ export const editSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () => (
|
|||
|
||||
const validationResult = validateMonitor(editedMonitor as MonitorFields);
|
||||
|
||||
if (!validationResult.valid) {
|
||||
if (!validationResult.valid || !validationResult.decodedMonitor) {
|
||||
const { reason: message, details, payload } = validationResult;
|
||||
return response.badRequest({ body: { message, attributes: { details, ...payload } } });
|
||||
}
|
||||
|
||||
const monitorWithRevision = {
|
||||
...editedMonitor,
|
||||
...validationResult.decodedMonitor,
|
||||
revision: (previousMonitor.attributes[ConfigKey.REVISION] || 0) + 1,
|
||||
};
|
||||
const formattedMonitor = formatSecrets(monitorWithRevision);
|
||||
|
@ -102,7 +102,7 @@ export const editSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () => (
|
|||
syntheticsMonitorClient,
|
||||
savedObjectsClient,
|
||||
request,
|
||||
normalizedMonitor: editedMonitor,
|
||||
normalizedMonitor: validationResult.decodedMonitor,
|
||||
monitorWithRevision: formattedMonitor,
|
||||
spaceId,
|
||||
});
|
||||
|
|
|
@ -109,6 +109,7 @@ describe('validateMonitor', () => {
|
|||
[ConfigKey.METADATA]: testMetaData,
|
||||
[ConfigKey.HOSTS]: 'https://host1.com',
|
||||
[ConfigKey.FORM_MONITOR_TYPE]: FormMonitorType.TCP,
|
||||
[ConfigKey.PORT]: null,
|
||||
};
|
||||
|
||||
testTCPAdvancedFields = {
|
||||
|
@ -131,6 +132,7 @@ describe('validateMonitor', () => {
|
|||
[ConfigKey.MAX_REDIRECTS]: '3',
|
||||
[ConfigKey.URLS]: 'https://example.com',
|
||||
[ConfigKey.FORM_MONITOR_TYPE]: FormMonitorType.HTTP,
|
||||
[ConfigKey.PORT]: null,
|
||||
};
|
||||
|
||||
testHTTPAdvancedFields = {
|
||||
|
@ -453,7 +455,8 @@ function getJsonPayload() {
|
|||
' },' +
|
||||
' "url": "https://example-url.com",' +
|
||||
' "isServiceManaged": true' +
|
||||
' }]' +
|
||||
' }],' +
|
||||
' "url.port": null' +
|
||||
'}';
|
||||
|
||||
return JSON.parse(json);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import * as t from 'io-ts';
|
||||
|
||||
import { isLeft } from 'fp-ts/lib/Either';
|
||||
import { formatErrors } from '@kbn/securitysolution-io-ts-utils';
|
||||
|
@ -19,6 +20,7 @@ import {
|
|||
ICMPSimpleFieldsCodec,
|
||||
MonitorFields,
|
||||
TCPFieldsCodec,
|
||||
SyntheticsMonitor,
|
||||
} from '../../../common/runtime_types';
|
||||
|
||||
type MonitorCodecType =
|
||||
|
@ -39,6 +41,7 @@ export interface ValidationResult {
|
|||
reason: string;
|
||||
details: string;
|
||||
payload: object;
|
||||
decodedMonitor?: SyntheticsMonitor;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,9 +61,10 @@ export function validateMonitor(monitorFields: MonitorFields): ValidationResult
|
|||
};
|
||||
}
|
||||
|
||||
const codec = monitorTypeToCodecMap[monitorType];
|
||||
// Cast it to ICMPCodec to satisfy typing. During runtime, correct codec will be used to decode.
|
||||
const SyntheticsMonitorCodec = monitorTypeToCodecMap[monitorType] as typeof ICMPSimpleFieldsCodec;
|
||||
|
||||
if (!codec) {
|
||||
if (!SyntheticsMonitorCodec) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: `Payload is not a valid monitor object`,
|
||||
|
@ -69,8 +73,8 @@ export function validateMonitor(monitorFields: MonitorFields): ValidationResult
|
|||
};
|
||||
}
|
||||
|
||||
// Cast it to ICMPCodec to satisfy typing. During runtime, correct codec will be used to decode.
|
||||
const decodedMonitor = (codec as typeof ICMPSimpleFieldsCodec).decode(monitorFields);
|
||||
const ExactSyntheticsMonitorCodec = t.exact(SyntheticsMonitorCodec);
|
||||
const decodedMonitor = ExactSyntheticsMonitorCodec.decode(monitorFields);
|
||||
|
||||
if (isLeft(decodedMonitor)) {
|
||||
return {
|
||||
|
@ -81,7 +85,13 @@ export function validateMonitor(monitorFields: MonitorFields): ValidationResult
|
|||
};
|
||||
}
|
||||
|
||||
return { valid: true, reason: '', details: '', payload: monitorFields };
|
||||
return {
|
||||
valid: true,
|
||||
reason: '',
|
||||
details: '',
|
||||
payload: monitorFields,
|
||||
decodedMonitor: decodedMonitor.right,
|
||||
};
|
||||
}
|
||||
|
||||
export function validateProjectMonitor(monitorFields: ProjectMonitor): ValidationResult {
|
||||
|
|
|
@ -26,7 +26,7 @@ export const runOnceSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () =
|
|||
|
||||
const validationResult = validateMonitor(monitor);
|
||||
|
||||
if (!validationResult.valid) {
|
||||
if (!validationResult.valid || !validationResult.decodedMonitor) {
|
||||
const { reason: message, details, payload } = validationResult;
|
||||
return response.badRequest({ body: { message, attributes: { details, ...payload } } });
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ export const runOnceSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () =
|
|||
const errors = await syntheticsService.runOnceConfigs([
|
||||
formatHeartbeatRequest({
|
||||
// making it enabled, even if it's disabled in the UI
|
||||
monitor: { ...monitor, enabled: true },
|
||||
monitor: { ...validationResult.decodedMonitor, enabled: true },
|
||||
monitorId,
|
||||
runOnce: true,
|
||||
}),
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
} from './common';
|
||||
import { BrowserFields, ConfigKey } from '../../../common/runtime_types/monitor_management';
|
||||
import { DEFAULT_BROWSER_ADVANCED_FIELDS } from '../../../common/constants/monitor_defaults';
|
||||
import { tlsFormatters } from './tls';
|
||||
|
||||
export type BrowserFormatMap = Record<keyof BrowserFields, Formatter>;
|
||||
|
||||
|
@ -66,10 +67,9 @@ export const browserFormatters: BrowserFormatMap = {
|
|||
[ConfigKey.JOURNEY_FILTERS_TAGS]: (fields) =>
|
||||
arrayFormatter(fields[ConfigKey.JOURNEY_FILTERS_TAGS]),
|
||||
[ConfigKey.IGNORE_HTTPS_ERRORS]: null,
|
||||
[ConfigKey.PROJECT_ID]: null,
|
||||
[ConfigKey.PLAYWRIGHT_OPTIONS]: (fields) =>
|
||||
stringToObjectFormatter(fields[ConfigKey.PLAYWRIGHT_OPTIONS] || ''),
|
||||
[ConfigKey.ORIGINAL_SPACE]: null,
|
||||
[ConfigKey.TEXT_ASSERTION]: null,
|
||||
...commonFormatters,
|
||||
...tlsFormatters,
|
||||
};
|
||||
|
|
|
@ -31,7 +31,9 @@ export const commonFormatters: CommonFormatMap = {
|
|||
fields[ConfigKey.MONITOR_SOURCE_TYPE] || SourceType.UI,
|
||||
[ConfigKey.FORM_MONITOR_TYPE]: null,
|
||||
[ConfigKey.JOURNEY_ID]: null,
|
||||
[ConfigKey.PROJECT_ID]: null,
|
||||
[ConfigKey.CUSTOM_HEARTBEAT_ID]: null,
|
||||
[ConfigKey.ORIGINAL_SPACE]: null,
|
||||
};
|
||||
|
||||
export const arrayFormatter = (value: string[] = []) => (value.length ? value : null);
|
||||
|
|
|
@ -14,6 +14,7 @@ export type HTTPFormatMap = Record<keyof HTTPFields, Formatter>;
|
|||
export const httpFormatters: HTTPFormatMap = {
|
||||
[ConfigKey.METADATA]: (fields) => objectFormatter(fields[ConfigKey.METADATA]),
|
||||
[ConfigKey.URLS]: null,
|
||||
[ConfigKey.PORT]: null,
|
||||
[ConfigKey.MAX_REDIRECTS]: null,
|
||||
[ConfigKey.USERNAME]: null,
|
||||
[ConfigKey.PASSWORD]: null,
|
||||
|
|
|
@ -14,6 +14,7 @@ export type TCPFormatMap = Record<keyof TCPFields, Formatter>;
|
|||
export const tcpFormatters: TCPFormatMap = {
|
||||
[ConfigKey.METADATA]: null,
|
||||
[ConfigKey.HOSTS]: null,
|
||||
[ConfigKey.PORT]: null,
|
||||
[ConfigKey.PROXY_URL]: null,
|
||||
[ConfigKey.PROXY_USE_LOCAL_RESOLVER]: null,
|
||||
[ConfigKey.RESPONSE_RECEIVE_CHECK]: null,
|
||||
|
|
|
@ -179,6 +179,7 @@ describe('http normalizers', () => {
|
|||
timeout: '80',
|
||||
type: 'http',
|
||||
urls: 'http://localhost:9200',
|
||||
'url.port': null,
|
||||
username: '',
|
||||
},
|
||||
unsupportedKeys: ['check.response.body', 'unsupportedKey.nestedUnsupportedKey'],
|
||||
|
@ -232,6 +233,7 @@ describe('http normalizers', () => {
|
|||
timeout: '80',
|
||||
type: 'http',
|
||||
urls: 'http://localhost:9200',
|
||||
'url.port': null,
|
||||
username: '',
|
||||
},
|
||||
unsupportedKeys: [],
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { Locations, LocationStatus, PrivateLocation } from '../../../../common/runtime_types';
|
||||
import { normalizeProjectMonitors } from '.';
|
||||
|
||||
describe('http normalizers', () => {
|
||||
describe('icmp normalizers', () => {
|
||||
describe('normalize push monitors', () => {
|
||||
const projectId = 'test-project-id';
|
||||
const locations: Locations = [
|
||||
|
@ -81,7 +81,7 @@ describe('http normalizers', () => {
|
|||
},
|
||||
];
|
||||
|
||||
it('properly normalizes http monitors', () => {
|
||||
it('properly normalizes icmp monitors', () => {
|
||||
const actual = normalizeProjectMonitors({
|
||||
locations,
|
||||
privateLocations,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { Locations, LocationStatus, PrivateLocation } from '../../../../common/runtime_types';
|
||||
import { normalizeProjectMonitors } from '.';
|
||||
|
||||
describe('http normalizers', () => {
|
||||
describe('tcp normalizers', () => {
|
||||
describe('normalize push monitors', () => {
|
||||
const projectId = 'test-project-id';
|
||||
const locations: Locations = [
|
||||
|
@ -83,7 +83,7 @@ describe('http normalizers', () => {
|
|||
},
|
||||
];
|
||||
|
||||
it('properly normalizes http monitors', () => {
|
||||
it('properly normalizes tcp monitors', () => {
|
||||
const actual = normalizeProjectMonitors({
|
||||
locations,
|
||||
privateLocations,
|
||||
|
@ -106,6 +106,7 @@ describe('http normalizers', () => {
|
|||
enabled: true,
|
||||
form_monitor_type: 'tcp',
|
||||
hosts: 'smtp.gmail.com:587',
|
||||
'url.port': null,
|
||||
journey_id: 'gmail-smtp',
|
||||
locations: [
|
||||
{
|
||||
|
@ -157,6 +158,7 @@ describe('http normalizers', () => {
|
|||
enabled: true,
|
||||
form_monitor_type: 'tcp',
|
||||
hosts: 'localhost:18278',
|
||||
'url.port': null,
|
||||
journey_id: 'always-down',
|
||||
locations: [
|
||||
{
|
||||
|
@ -221,6 +223,7 @@ describe('http normalizers', () => {
|
|||
enabled: true,
|
||||
form_monitor_type: 'tcp',
|
||||
hosts: 'localhost',
|
||||
'url.port': null,
|
||||
journey_id: 'always-down',
|
||||
locations: [
|
||||
{
|
||||
|
|
|
@ -19,7 +19,6 @@ import { deleteMonitorBulk } from '../../routes/monitor_cruds/bulk_cruds/delete_
|
|||
import { SyntheticsMonitorClient } from '../synthetics_monitor/synthetics_monitor_client';
|
||||
import { syncEditedMonitorBulk } from '../../routes/monitor_cruds/bulk_cruds/edit_monitor_bulk';
|
||||
import {
|
||||
BrowserFields,
|
||||
ConfigKey,
|
||||
SyntheticsMonitorWithSecrets,
|
||||
EncryptedSyntheticsMonitor,
|
||||
|
@ -124,16 +123,16 @@ export class ProjectMonitorFormatter {
|
|||
const existingMonitors = await this.getProjectMonitorsForProject();
|
||||
this.staleMonitorsMap = await this.getStaleMonitorsMap(existingMonitors);
|
||||
|
||||
const normalizedNewMonitors: BrowserFields[] = [];
|
||||
const normalizedNewMonitors: SyntheticsMonitor[] = [];
|
||||
const normalizedUpdateMonitors: Array<{
|
||||
previousMonitor: SavedObjectsFindResult<EncryptedSyntheticsMonitor>;
|
||||
monitor: BrowserFields;
|
||||
monitor: SyntheticsMonitor;
|
||||
}> = [];
|
||||
|
||||
for (const monitor of this.monitors) {
|
||||
const previousMonitor = existingMonitors.find(
|
||||
(monitorObj) =>
|
||||
(monitorObj.attributes as BrowserFields)[ConfigKey.JOURNEY_ID] === monitor.id
|
||||
(monitorObj.attributes as SyntheticsMonitor)[ConfigKey.JOURNEY_ID] === monitor.id
|
||||
);
|
||||
|
||||
const normM = await this.validateProjectMonitor({
|
||||
|
@ -154,7 +153,7 @@ export class ProjectMonitorFormatter {
|
|||
|
||||
await this.createMonitorsBulk(normalizedNewMonitors);
|
||||
|
||||
const { updatedCount } = await this.updateMonitors(normalizedUpdateMonitors);
|
||||
const { updatedCount } = await this.updateMonitorsBulk(normalizedUpdateMonitors);
|
||||
|
||||
if (normalizedUpdateMonitors.length > 0) {
|
||||
let updateMessage = '';
|
||||
|
@ -228,16 +227,16 @@ export class ProjectMonitorFormatter {
|
|||
}
|
||||
|
||||
/* Validates that the normalized monitor is a valid monitor saved object type */
|
||||
const { valid: isNormalizedMonitorValid } = this.validateMonitor({
|
||||
const { valid: isNormalizedMonitorValid, decodedMonitor } = this.validateMonitor({
|
||||
validationResult: validateMonitor(normalizedMonitor as MonitorFields),
|
||||
monitorId: monitor.id,
|
||||
});
|
||||
|
||||
if (!isNormalizedMonitorValid) {
|
||||
if (!isNormalizedMonitorValid || !decodedMonitor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return normalizedMonitor;
|
||||
return decodedMonitor;
|
||||
} catch (e) {
|
||||
this.server.logger.error(e);
|
||||
this.failedMonitors.push({
|
||||
|
@ -259,7 +258,7 @@ export class ProjectMonitorFormatter {
|
|||
const staleMonitors: StaleMonitorMap = {};
|
||||
|
||||
existingMonitors.forEach((savedObject) => {
|
||||
const journeyId = (savedObject.attributes as BrowserFields)[ConfigKey.JOURNEY_ID];
|
||||
const journeyId = (savedObject.attributes as SyntheticsMonitor)[ConfigKey.JOURNEY_ID];
|
||||
if (journeyId) {
|
||||
staleMonitors[journeyId] = {
|
||||
stale: true,
|
||||
|
@ -291,7 +290,7 @@ export class ProjectMonitorFormatter {
|
|||
return hits;
|
||||
};
|
||||
|
||||
private createMonitorsBulk = async (monitors: BrowserFields[]) => {
|
||||
private createMonitorsBulk = async (monitors: SyntheticsMonitor[]) => {
|
||||
try {
|
||||
if (monitors.length > 0) {
|
||||
const { newMonitors } = await syncNewMonitorBulk({
|
||||
|
@ -352,9 +351,9 @@ export class ProjectMonitorFormatter {
|
|||
);
|
||||
};
|
||||
|
||||
private updateMonitors = async (
|
||||
private updateMonitorsBulk = async (
|
||||
monitors: Array<{
|
||||
monitor: BrowserFields;
|
||||
monitor: SyntheticsMonitor;
|
||||
previousMonitor: SavedObjectsFindResult<EncryptedSyntheticsMonitor>;
|
||||
}>
|
||||
): Promise<{
|
||||
|
|
|
@ -140,6 +140,41 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
expect(apiResponse.status).eql(400);
|
||||
});
|
||||
|
||||
it('omits unknown keys', async () => {
|
||||
// Delete a required property to make payload invalid
|
||||
const newMonitor = {
|
||||
name: 'Sample name',
|
||||
url: 'https://elastic.co',
|
||||
unknownKey: 'unknownValue',
|
||||
type: 'http',
|
||||
locations: [
|
||||
{
|
||||
id: 'eu-west-01',
|
||||
label: 'Europe West',
|
||||
geo: {
|
||||
lat: 33.2343132435,
|
||||
lon: 73.2342343434,
|
||||
},
|
||||
url: 'https://example-url.com',
|
||||
isServiceManaged: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const apiResponse = await supertestAPI
|
||||
.post(API_URLS.SYNTHETICS_MONITORS)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(newMonitor)
|
||||
.expect(200);
|
||||
|
||||
const response = await supertestAPI
|
||||
.get(`${API_URLS.SYNTHETICS_MONITORS}/${apiResponse.body.id}`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
|
||||
expect(response.body.attributes).not.to.have.keys('unknownkey', 'url');
|
||||
});
|
||||
|
||||
it('can create monitor with API key with proper permissions', async () => {
|
||||
await supertestAPI
|
||||
.post('/internal/security/api_key')
|
||||
|
|
|
@ -96,6 +96,114 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
icmpProjectMonitors = setUniqueIds(getFixtureJson('project_icmp_monitor'));
|
||||
});
|
||||
|
||||
it('project monitors - handles browser monitors', async () => {
|
||||
const successfulMonitors = [projectMonitors.monitors[0]];
|
||||
|
||||
try {
|
||||
const messages = await parseStreamApiResponse(
|
||||
projectMonitorEndpoint,
|
||||
JSON.stringify(projectMonitors)
|
||||
);
|
||||
|
||||
expect(messages).to.have.length(2);
|
||||
expect(messages[1].updatedMonitors).eql([]);
|
||||
expect(messages[1].createdMonitors).eql(successfulMonitors.map((monitor) => monitor.id));
|
||||
expect(messages[1].failedMonitors).eql([]);
|
||||
|
||||
for (const monitor of successfulMonitors) {
|
||||
const journeyId = monitor.id;
|
||||
const createdMonitorsResponse = await supertest
|
||||
.get(API_URLS.SYNTHETICS_MONITORS)
|
||||
.query({ filter: `${syntheticsMonitorType}.attributes.journey_id: ${journeyId}` })
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
|
||||
const decryptedCreatedMonitor = await supertest
|
||||
.get(`${API_URLS.SYNTHETICS_MONITORS}/${createdMonitorsResponse.body.monitors[0].id}`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
|
||||
expect(decryptedCreatedMonitor.body.attributes).to.eql({
|
||||
__ui: {
|
||||
is_zip_url_tls_enabled: false,
|
||||
script_source: {
|
||||
file_name: '',
|
||||
is_generated_script: false,
|
||||
},
|
||||
},
|
||||
config_id: '',
|
||||
custom_heartbeat_id: `${journeyId}-test-suite-default`,
|
||||
enabled: true,
|
||||
'filter_journeys.match': 'check if title is present',
|
||||
'filter_journeys.tags': [],
|
||||
form_monitor_type: 'multistep',
|
||||
ignore_https_errors: false,
|
||||
journey_id: journeyId,
|
||||
locations: [
|
||||
{
|
||||
geo: {
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
},
|
||||
id: 'localhost',
|
||||
isInvalid: false,
|
||||
isServiceManaged: true,
|
||||
label: 'Local Synthetics Service',
|
||||
status: 'experimental',
|
||||
url: 'mockDevUrl',
|
||||
},
|
||||
],
|
||||
name: 'check if title is present',
|
||||
namespace: 'default',
|
||||
origin: 'project',
|
||||
original_space: 'default',
|
||||
playwright_options: '{"headless":true,"chromiumSandbox":false}',
|
||||
playwright_text_assertion: '',
|
||||
project_id: 'test-suite',
|
||||
params: '',
|
||||
revision: 1,
|
||||
schedule: {
|
||||
number: '10',
|
||||
unit: 'm',
|
||||
},
|
||||
screenshots: 'on',
|
||||
'service.name': '',
|
||||
'source.zip_url.folder': '',
|
||||
'source.zip_url.proxy_url': '',
|
||||
'source.zip_url.url': '',
|
||||
'source.zip_url.password': '',
|
||||
'source.zip_url.username': '',
|
||||
synthetics_args: [],
|
||||
tags: [],
|
||||
'throttling.config': '5d/3u/20l',
|
||||
'throttling.download_speed': '5',
|
||||
'throttling.is_enabled': true,
|
||||
'throttling.latency': '20',
|
||||
'throttling.upload_speed': '3',
|
||||
'ssl.certificate': '',
|
||||
'ssl.certificate_authorities': '',
|
||||
'ssl.supported_protocols': ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'],
|
||||
'ssl.verification_mode': 'full',
|
||||
'ssl.key': '',
|
||||
'ssl.key_passphrase': '',
|
||||
'source.inline.script': '',
|
||||
'source.project.content':
|
||||
'UEsDBBQACAAIAON5qVQAAAAAAAAAAAAAAAAfAAAAZXhhbXBsZXMvdG9kb3MvYmFzaWMuam91cm5leS50c22Q0WrDMAxF3/sVF7MHB0LMXlc6RvcN+wDPVWNviW0sdUsp/fe5SSiD7UFCWFfHujIGlpnkybwxFTZfoY/E3hsaLEtwhs9RPNWKDU12zAOxkXRIbN4tB9d9pFOJdO6EN2HMqQguWN9asFBuQVMmJ7jiWNII9fIXrbabdUYr58l9IhwhQQZCYORCTFFUC31Btj21NRc7Mq4Nds+4bDD/pNVgT9F52Jyr2Fa+g75LAPttg8yErk+S9ELpTmVotlVwnfNCuh2lepl3+JflUmSBJ3uggt1v9INW/lHNLKze9dJe1J3QJK8pSvWkm6aTtCet5puq+x63+AFQSwcIAPQ3VfcAAACcAQAAUEsBAi0DFAAIAAgA43mpVAD0N1X3AAAAnAEAAB8AAAAAAAAAAAAgAKSBAAAAAGV4YW1wbGVzL3RvZG9zL2Jhc2ljLmpvdXJuZXkudHNQSwUGAAAAAAEAAQBNAAAARAEAAAAA',
|
||||
timeout: null,
|
||||
type: 'browser',
|
||||
'url.port': null,
|
||||
urls: '',
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
await Promise.all([
|
||||
successfulMonitors.map((monitor) => {
|
||||
return deleteMonitor(monitor.id, httpProjectMonitors.project);
|
||||
}),
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
it('project monitors - handles http monitors', async () => {
|
||||
const kibanaVersion = await kibanaServer.version.get();
|
||||
const successfulMonitors = [httpProjectMonitors.monitors[1]];
|
||||
|
@ -130,7 +238,12 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
|
||||
expect(createdMonitorsResponse.body.monitors[0].attributes).to.eql({
|
||||
const decryptedCreatedMonitor = await supertest
|
||||
.get(`${API_URLS.SYNTHETICS_MONITORS}/${createdMonitorsResponse.body.monitors[0].id}`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
|
||||
expect(decryptedCreatedMonitor.body.attributes).to.eql({
|
||||
__ui: {
|
||||
is_tls_enabled: false,
|
||||
},
|
||||
|
@ -138,6 +251,16 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
'check.response.status': ['200'],
|
||||
config_id: '',
|
||||
custom_heartbeat_id: `${journeyId}-test-suite-default`,
|
||||
'check.response.body.negative': [],
|
||||
'check.response.body.positive': ['Saved', 'saved'],
|
||||
'check.response.headers': {},
|
||||
'check.request.body': {
|
||||
type: 'text',
|
||||
value: '',
|
||||
},
|
||||
'check.request.headers': {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
enabled: false,
|
||||
form_monitor_type: 'http',
|
||||
journey_id: journeyId,
|
||||
|
@ -161,6 +284,8 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
origin: 'project',
|
||||
original_space: 'default',
|
||||
project_id: 'test-suite',
|
||||
username: '',
|
||||
password: '',
|
||||
proxy_url: '',
|
||||
'response.include_body': 'always',
|
||||
'response.include_headers': false,
|
||||
|
@ -174,10 +299,13 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
'ssl.certificate_authorities': '',
|
||||
'ssl.supported_protocols': ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'],
|
||||
'ssl.verification_mode': 'full',
|
||||
'ssl.key': '',
|
||||
'ssl.key_passphrase': '',
|
||||
tags: Array.isArray(monitor.tags) ? monitor.tags : monitor.tags?.split(','),
|
||||
timeout: '80',
|
||||
type: 'http',
|
||||
urls: Array.isArray(monitor.urls) ? monitor.urls?.[0] : monitor.urls,
|
||||
'url.port': null,
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
|
@ -223,12 +351,19 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
|
||||
expect(createdMonitorsResponse.body.monitors[0].attributes).to.eql({
|
||||
const decryptedCreatedMonitor = await supertest
|
||||
.get(`${API_URLS.SYNTHETICS_MONITORS}/${createdMonitorsResponse.body.monitors[0].id}`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
|
||||
expect(decryptedCreatedMonitor.body.attributes).to.eql({
|
||||
__ui: {
|
||||
is_tls_enabled: false,
|
||||
},
|
||||
config_id: '',
|
||||
custom_heartbeat_id: `${journeyId}-test-suite-default`,
|
||||
'check.receive': '',
|
||||
'check.send': '',
|
||||
enabled: true,
|
||||
form_monitor_type: 'tcp',
|
||||
journey_id: journeyId,
|
||||
|
@ -263,10 +398,13 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
'ssl.certificate_authorities': '',
|
||||
'ssl.supported_protocols': ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'],
|
||||
'ssl.verification_mode': 'full',
|
||||
'ssl.key': '',
|
||||
'ssl.key_passphrase': '',
|
||||
tags: Array.isArray(monitor.tags) ? monitor.tags : monitor.tags?.split(','),
|
||||
timeout: '16',
|
||||
type: 'tcp',
|
||||
hosts: Array.isArray(monitor.hosts) ? monitor.hosts?.[0] : monitor.hosts,
|
||||
'url.port': null,
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
|
@ -312,7 +450,12 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
|
||||
expect(createdMonitorsResponse.body.monitors[0].attributes).to.eql({
|
||||
const decryptedCreatedMonitor = await supertest
|
||||
.get(`${API_URLS.SYNTHETICS_MONITORS}/${createdMonitorsResponse.body.monitors[0].id}`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
|
||||
expect(decryptedCreatedMonitor.body.attributes).to.eql({
|
||||
config_id: '',
|
||||
custom_heartbeat_id: `${journeyId}-test-suite-default`,
|
||||
enabled: true,
|
||||
|
|
|
@ -16,7 +16,7 @@ import { getFixtureJson } from './helper/get_fixture_json';
|
|||
import { PrivateLocationTestService } from './services/private_location_test_service';
|
||||
|
||||
export default function ({ getService }: FtrProviderContext) {
|
||||
describe('[PUT] /internal/uptime/service/monitors', function () {
|
||||
describe('EditMonitor', function () {
|
||||
this.tags('skipCloud');
|
||||
|
||||
const supertest = getService('supertest');
|
||||
|
@ -109,6 +109,66 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
);
|
||||
});
|
||||
|
||||
it('strips unknown keys from monitor edits', async () => {
|
||||
const newMonitor = httpMonitorJson;
|
||||
|
||||
const { id: monitorId, attributes: savedMonitor } = await saveMonitor(
|
||||
newMonitor as MonitorFields
|
||||
);
|
||||
|
||||
expect(savedMonitor).eql(omit(newMonitor, secretKeys));
|
||||
|
||||
const updates: Partial<HTTPFields> = {
|
||||
[ConfigKey.URLS]: 'https://modified-host.com',
|
||||
[ConfigKey.NAME]: 'Modified name',
|
||||
[ConfigKey.LOCATIONS]: [
|
||||
{
|
||||
id: 'eu-west-01',
|
||||
label: 'Europe West',
|
||||
geo: {
|
||||
lat: 33.2343132435,
|
||||
lon: 73.2342343434,
|
||||
},
|
||||
url: 'https://example-url.com',
|
||||
isServiceManaged: true,
|
||||
},
|
||||
],
|
||||
[ConfigKey.REQUEST_HEADERS_CHECK]: {
|
||||
sampleHeader2: 'sampleValue2',
|
||||
},
|
||||
[ConfigKey.METADATA]: {
|
||||
script_source: {
|
||||
is_generated_script: false,
|
||||
file_name: 'test-file.name',
|
||||
},
|
||||
},
|
||||
unknownkey: 'unknownvalue',
|
||||
} as Partial<HTTPFields>;
|
||||
|
||||
const modifiedMonitor = omit(
|
||||
{
|
||||
...newMonitor,
|
||||
...updates,
|
||||
[ConfigKey.METADATA]: {
|
||||
...newMonitor[ConfigKey.METADATA],
|
||||
...updates[ConfigKey.METADATA],
|
||||
},
|
||||
},
|
||||
['unknownkey']
|
||||
);
|
||||
|
||||
const editResponse = await supertest
|
||||
.put(API_URLS.SYNTHETICS_MONITORS + '/' + monitorId)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(modifiedMonitor)
|
||||
.expect(200);
|
||||
|
||||
expect(editResponse.body.attributes).eql(
|
||||
omit({ ...modifiedMonitor, revision: 2 }, secretKeys)
|
||||
);
|
||||
expect(editResponse.body.attributes).not.to.have.keys('unknownkey');
|
||||
});
|
||||
|
||||
it('returns 404 if monitor id is not present', async () => {
|
||||
const invalidMonitorId = 'invalid-id';
|
||||
const expected404Message = `Monitor id ${invalidMonitorId} not found!`;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
"max_redirects": "3",
|
||||
"password": "test",
|
||||
"urls": "https://nextjs-test-synthetics.vercel.app/api/users",
|
||||
"url.port": null,
|
||||
"proxy_url": "http://proxy.com",
|
||||
"check.response.body.negative": [],
|
||||
"check.response.body.positive": [],
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"type": "tcp",
|
||||
"type": "icmp",
|
||||
"locations": [],
|
||||
"journey_id": "",
|
||||
"enabled": true,
|
||||
|
@ -14,25 +14,8 @@
|
|||
"tagT2"
|
||||
],
|
||||
"timeout": "16",
|
||||
"__ui": {
|
||||
"is_tls_enabled": true,
|
||||
"is_zip_url_tls_enabled": false
|
||||
},
|
||||
"hosts": "192.33.22.111:3333",
|
||||
"proxy_url": "",
|
||||
"proxy_use_local_resolver": false,
|
||||
"check.receive": "",
|
||||
"check.send": "",
|
||||
"ssl.certificate_authorities": "",
|
||||
"ssl.certificate": "",
|
||||
"ssl.key": "",
|
||||
"ssl.key_passphrase": "",
|
||||
"ssl.verification_mode": "full",
|
||||
"ssl.supported_protocols": [
|
||||
"TLSv1.1",
|
||||
"TLSv1.2",
|
||||
"TLSv1.3"
|
||||
],
|
||||
"wait": "1",
|
||||
"name": "Test HTTP Monitor 04",
|
||||
"namespace": "testnamespace",
|
||||
"origin": "ui",
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
"is_zip_url_tls_enabled": false
|
||||
},
|
||||
"hosts": "example-host:40",
|
||||
"url.port": null,
|
||||
"proxy_url": "",
|
||||
"proxy_use_local_resolver": false,
|
||||
"check.receive": "",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue