Skip to content

Commit

Permalink
[Synthetics] enable/disable - prevent incorrect keys from being added…
Browse files Browse the repository at this point in the history
… to the monitor saved object (#140553) (#142238)

* 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 <[email protected]>
(cherry picked from commit 27916d3)

Co-authored-by: Dominique Clarke <[email protected]>
  • Loading branch information
kibanamachine and dominiqueclarke authored Sep 29, 2022
1 parent b247f29 commit c5e9eb8
Show file tree
Hide file tree
Showing 37 changed files with 339 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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 = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
tlsValueToStringFormatter,
tlsArrayToYamlFormatter,
} from '../tls/formatters';
import { tlsFormatters } from '../tls/formatters';

export type BrowserFormatMap = Record<keyof BrowserFields, Formatter>;

Expand Down Expand Up @@ -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,
};
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = []) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}),
]);
Expand All @@ -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,
]);
Expand Down Expand Up @@ -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,
]);
Expand Down Expand Up @@ -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,
}),
]),
Expand All @@ -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),
Expand All @@ -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([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ describe('format', () => {
timeout: '16',
type: 'http',
urls: 'sample url',
'url.port': null,
username: '',
});
});
Expand Down Expand Up @@ -347,6 +348,7 @@ describe('format', () => {
timeout: '16',
type: 'http',
urls: 'sample url',
'url.port': null,
username: '',
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const MonitorEnabled = ({

const handleEnabledChange = (event: EuiSwitchEvent) => {
const checked = event.target.checked;
updateMonitorEnabledState(monitor, checked);
updateMonitorEnabledState(checked);
};

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand All @@ -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]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export function ActionsPopover({
icon: 'invert',
onClick: () => {
if (status !== FETCH_STATUS.LOADING)
updateMonitorEnabledState(monitor, !monitor.isEnabled);
updateMonitorEnabledState(!monitor.isEnabled);
},
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 },
})
);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { createAction } from '@reduxjs/toolkit';
import {
EncryptedSyntheticsMonitor,
MonitorManagementListResult,
MonitorOverviewItem,
} from '../../../../../common/runtime_types';
import { createAsyncAction } from '../utils/actions';

Expand All @@ -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<{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
FetchMonitorManagementListQueryArgs,
MonitorManagementListResult,
MonitorManagementListResultCodec,
MonitorOverviewItem,
ServiceLocationErrors,
SyntheticsMonitor,
} from '../../../../../common/runtime_types';
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
LocationStatus,
ScheduleUnit,
SourceType,
VerificationMode,
TLSVersion,
} from '../../../../../../common/runtime_types';

/**
Expand Down Expand Up @@ -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',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
getNormalizer,
getJsonToJavascriptNormalizer,
} from '../common/normalizers';
import { tlsNormalizers } from '../tls/normalizers';

import { defaultBrowserSimpleFields, defaultBrowserAdvancedFields } from '../contexts';

Expand Down Expand Up @@ -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,
};
Original file line number Diff line number Diff line change
Expand Up @@ -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),
};
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 } } });
}
Expand All @@ -78,8 +78,7 @@ export const addSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () => ({

try {
const { errors, newMonitor } = await syncNewMonitor({
normalizedMonitor: monitorWithDefaults,
monitor,
normalizedMonitor: validationResult.decodedMonitor,
server,
syntheticsMonitorClient,
savedObjectsClient,
Expand Down Expand Up @@ -140,7 +139,6 @@ export const createNewSavedObjectMonitor = async ({

export const syncNewMonitor = async ({
id,
monitor,
server,
syntheticsMonitorClient,
savedObjectsClient,
Expand All @@ -150,7 +148,6 @@ export const syncNewMonitor = async ({
spaceId,
}: {
id?: string;
monitor: SyntheticsMonitor;
normalizedMonitor: SyntheticsMonitor;
server: UptimeServerSetup;
syntheticsMonitorClient: SyntheticsMonitorClient;
Expand Down Expand Up @@ -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,
})
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -102,7 +102,7 @@ export const editSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () => (
syntheticsMonitorClient,
savedObjectsClient,
request,
normalizedMonitor: editedMonitor,
normalizedMonitor: validationResult.decodedMonitor,
monitorWithRevision: formattedMonitor,
spaceId,
});
Expand Down
Loading

0 comments on commit c5e9eb8

Please sign in to comment.