diff --git a/x-pack/plugins/uptime/common/config.ts b/x-pack/plugins/uptime/common/config.ts index 678ca8009bf24..c5dece689db51 100644 --- a/x-pack/plugins/uptime/common/config.ts +++ b/x-pack/plugins/uptime/common/config.ts @@ -21,28 +21,12 @@ const serviceConfig = schema.object({ const uptimeConfig = schema.object({ index: schema.maybe(schema.string()), - ui: schema.maybe( - schema.object({ - monitorManagement: schema.maybe( - schema.object({ - enabled: schema.boolean(), - }) - ), - }) - ), service: schema.maybe(serviceConfig), }); export const config: PluginConfigDescriptor = { - exposeToBrowser: { - ui: true, - }, schema: uptimeConfig, }; export type UptimeConfig = TypeOf; export type ServiceConfig = TypeOf; - -export interface UptimeUiConfig { - ui?: TypeOf['ui']; -} diff --git a/x-pack/plugins/uptime/common/constants/rest_api.ts b/x-pack/plugins/uptime/common/constants/rest_api.ts index f1b0b69ba61ec..c163718e0fc13 100644 --- a/x-pack/plugins/uptime/common/constants/rest_api.ts +++ b/x-pack/plugins/uptime/common/constants/rest_api.ts @@ -42,4 +42,5 @@ export enum API_URLS { SYNTHETICS_MONITORS = '/internal/uptime/service/monitors', RUN_ONCE_MONITOR = '/internal/uptime/service/monitors/run_once', TRIGGER_MONITOR = '/internal/uptime/service/monitors/trigger', + SERVICE_ALLOWED = '/internal/uptime/service/allowed', } diff --git a/x-pack/plugins/uptime/common/types/synthetics_monitor.ts b/x-pack/plugins/uptime/common/types/synthetics_monitor.ts index ec6b87bb0bf53..f4f20fda9235f 100644 --- a/x-pack/plugins/uptime/common/types/synthetics_monitor.ts +++ b/x-pack/plugins/uptime/common/types/synthetics_monitor.ts @@ -15,3 +15,7 @@ export interface MonitorIdParam { export type SyntheticsMonitorSavedObject = SimpleSavedObject & { updated_at: string; }; + +export interface SyntheticsServiceAllowed { + serviceAllowed: boolean; +} diff --git a/x-pack/plugins/uptime/e2e/config.ts b/x-pack/plugins/uptime/e2e/config.ts index 08cc1d960d044..66b97641b2156 100644 --- a/x-pack/plugins/uptime/e2e/config.ts +++ b/x-pack/plugins/uptime/e2e/config.ts @@ -63,7 +63,6 @@ async function config({ readConfigFile }: FtrConfigProviderContext) { : 'localKibanaIntegrationTestsUser' }`, `--xpack.uptime.service.password=${servicPassword}`, - '--xpack.uptime.ui.monitorManagement.enabled=true', ], }, }; diff --git a/x-pack/plugins/uptime/public/apps/plugin.ts b/x-pack/plugins/uptime/public/apps/plugin.ts index 278ce45cdf593..0751ea58cfd14 100644 --- a/x-pack/plugins/uptime/public/apps/plugin.ts +++ b/x-pack/plugins/uptime/public/apps/plugin.ts @@ -48,7 +48,6 @@ import { } from '../components/fleet_package'; import { LazySyntheticsCustomAssetsExtension } from '../components/fleet_package/lazy_synthetics_custom_assets_extension'; import { Start as InspectorPluginStart } from '../../../../../src/plugins/inspector/public'; -import { UptimeUiConfig } from '../../common/config'; import { CasesUiStart } from '../../../cases/public'; export interface ClientPluginsSetup { @@ -87,7 +86,6 @@ export class UptimePlugin constructor(private readonly initContext: PluginInitializerContext) {} public setup(core: CoreSetup, plugins: ClientPluginsSetup): void { - const config = this.initContext.config.get(); if (plugins.home) { plugins.home.featureCatalogue.register({ id: PLUGIN.ID, @@ -215,14 +213,7 @@ export class UptimePlugin const [coreStart, corePlugins] = await core.getStartServices(); const { renderApp } = await import('./render_app'); - return renderApp( - coreStart, - plugins, - corePlugins, - params, - config, - this.initContext.env.mode.dev - ); + return renderApp(coreStart, plugins, corePlugins, params, this.initContext.env.mode.dev); }, }); } diff --git a/x-pack/plugins/uptime/public/apps/render_app.tsx b/x-pack/plugins/uptime/public/apps/render_app.tsx index 44e9651c25dd1..653ac76c4c544 100644 --- a/x-pack/plugins/uptime/public/apps/render_app.tsx +++ b/x-pack/plugins/uptime/public/apps/render_app.tsx @@ -17,7 +17,6 @@ import { } from '../../common/constants'; import { UptimeApp, UptimeAppProps } from './uptime_app'; import { ClientPluginsSetup, ClientPluginsStart } from './plugin'; -import { UptimeUiConfig } from '../../common/config'; import { uptimeOverviewNavigatorParams } from './locators/overview'; export function renderApp( @@ -25,7 +24,6 @@ export function renderApp( plugins: ClientPluginsSetup, startPlugins: ClientPluginsStart, appMountParameters: AppMountParameters, - config: UptimeUiConfig, isDev: boolean ) { const { @@ -77,7 +75,6 @@ export function renderApp( setBadge, appMountParameters, setBreadcrumbs: core.chrome.setBreadcrumbs, - config, }; ReactDOM.render(, appMountParameters.element); diff --git a/x-pack/plugins/uptime/public/apps/uptime_app.tsx b/x-pack/plugins/uptime/public/apps/uptime_app.tsx index 12519143d347a..4387da4038061 100644 --- a/x-pack/plugins/uptime/public/apps/uptime_app.tsx +++ b/x-pack/plugins/uptime/public/apps/uptime_app.tsx @@ -35,7 +35,6 @@ import { EuiThemeProvider } from '../../../../../src/plugins/kibana_react/common import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { UptimeIndexPatternContextProvider } from '../contexts/uptime_index_pattern_context'; import { InspectorContextProvider } from '../../../observability/public'; -import { UptimeUiConfig } from '../../common/config'; export interface UptimeAppColors { danger: string; @@ -64,7 +63,6 @@ export interface UptimeAppProps { commonlyUsedRanges: CommonlyUsedRange[]; setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; appMountParameters: AppMountParameters; - config: UptimeUiConfig; isDev: boolean; } @@ -80,7 +78,6 @@ const Application = (props: UptimeAppProps) => { setBadge, startPlugins, appMountParameters, - config, } = props; useEffect(() => { @@ -138,11 +135,8 @@ const Application = (props: UptimeAppProps) => { > - - + + diff --git a/x-pack/plugins/uptime/public/components/common/header/action_menu.tsx b/x-pack/plugins/uptime/public/components/common/header/action_menu.tsx index f2a17c9aef99d..7faa2fbc294cd 100644 --- a/x-pack/plugins/uptime/public/components/common/header/action_menu.tsx +++ b/x-pack/plugins/uptime/public/components/common/header/action_menu.tsx @@ -9,19 +9,12 @@ import React from 'react'; import { HeaderMenuPortal } from '../../../../../observability/public'; import { AppMountParameters } from '../../../../../../../src/core/public'; import { ActionMenuContent } from './action_menu_content'; -import { UptimeConfig } from '../../../../common/config'; -export const ActionMenu = ({ - appMountParameters, - config, -}: { - appMountParameters: AppMountParameters; - config: UptimeConfig; -}) => ( +export const ActionMenu = ({ appMountParameters }: { appMountParameters: AppMountParameters }) => ( - + ); diff --git a/x-pack/plugins/uptime/public/components/common/header/action_menu_content.test.tsx b/x-pack/plugins/uptime/public/components/common/header/action_menu_content.test.tsx index 24c0ab86efc58..89aaec5f133c2 100644 --- a/x-pack/plugins/uptime/public/components/common/header/action_menu_content.test.tsx +++ b/x-pack/plugins/uptime/public/components/common/header/action_menu_content.test.tsx @@ -12,7 +12,7 @@ import { ActionMenuContent } from './action_menu_content'; describe('ActionMenuContent', () => { it('renders alerts dropdown', async () => { - const { getByLabelText, getByText } = render(); + const { getByLabelText, getByText } = render(); const alertsDropdown = getByLabelText('Open alerts and rules context menu'); fireEvent.click(alertsDropdown); @@ -24,7 +24,7 @@ describe('ActionMenuContent', () => { }); it('renders settings link', () => { - const { getByRole, getByText } = render(); + const { getByRole, getByText } = render(); const settingsAnchor = getByRole('link', { name: 'Navigate to the Uptime settings page' }); expect(settingsAnchor.getAttribute('href')).toBe('/settings'); @@ -32,7 +32,7 @@ describe('ActionMenuContent', () => { }); it('renders exploratory view link', () => { - const { getByLabelText, getByText } = render(); + const { getByLabelText, getByText } = render(); const analyzeAnchor = getByLabelText( 'Navigate to the "Explore Data" view to visualize Synthetics/User data' @@ -43,7 +43,7 @@ describe('ActionMenuContent', () => { }); it('renders Add Data link', () => { - const { getByLabelText, getByText } = render(); + const { getByLabelText, getByText } = render(); const addDataAnchor = getByLabelText('Navigate to a tutorial about adding Uptime data'); diff --git a/x-pack/plugins/uptime/public/components/common/header/action_menu_content.tsx b/x-pack/plugins/uptime/public/components/common/header/action_menu_content.tsx index 0c059580b5461..f83c71ada73a9 100644 --- a/x-pack/plugins/uptime/public/components/common/header/action_menu_content.tsx +++ b/x-pack/plugins/uptime/public/components/common/header/action_menu_content.tsx @@ -24,7 +24,6 @@ import { import { stringifyUrlParams } from '../../../lib/helper/stringify_url_params'; import { InspectorHeaderLink } from './inspector_header_link'; import { monitorStatusSelector } from '../../../state/selectors'; -import { UptimeConfig } from '../../../../common/config'; const ADD_DATA_LABEL = i18n.translate('xpack.uptime.addDataButtonLabel', { defaultMessage: 'Add data', @@ -39,7 +38,7 @@ const ANALYZE_MESSAGE = i18n.translate('xpack.uptime.analyzeDataButtonLabel.mess 'Explore Data allows you to select and filter result data in any dimension and look for the cause or impact of performance problems.', }); -export function ActionMenuContent({ config }: { config: UptimeConfig }): React.ReactElement { +export function ActionMenuContent(): React.ReactElement { const kibana = useKibana(); const { basePath } = useUptimeSettingsContext(); const params = useGetUrlParams(); @@ -77,23 +76,21 @@ export function ActionMenuContent({ config }: { config: UptimeConfig }): React.R return ( - {config.ui?.monitorManagement?.enabled && ( - - - - )} + + + { +export const AddMonitorBtn = () => { const history = useHistory(); + const { isAllowed, loading } = useSyntheticsServiceAllowed(); + + const canSave: boolean = !!useKibana().services?.application?.capabilities.uptime.save; + return ( { + const dispatch = useDispatch(); + + useEffect(() => { + dispatch(getSyntheticsServiceAllowed.get()); + }, [dispatch]); + + return useSelector(syntheticsServiceAllowedSelector); +}; diff --git a/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/invalid_monitors.tsx b/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/invalid_monitors.tsx index 4b524a2b52312..e00079605ba5d 100644 --- a/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/invalid_monitors.tsx +++ b/x-pack/plugins/uptime/public/components/monitor_management/monitor_list/invalid_monitors.tsx @@ -6,8 +6,10 @@ */ import React from 'react'; +import { useSelector } from 'react-redux'; import { MonitorManagementList, MonitorManagementListPageState } from './monitor_list'; import { MonitorManagementListResult, Ping } from '../../../../common/runtime_types'; +import { monitorManagementListSelector } from '../../../state/selectors'; interface Props { loading: boolean; @@ -31,6 +33,8 @@ export const InvalidMonitors = ({ const startIndex = (pageIndex - 1) * pageSize; + const monitorList = useSelector(monitorManagementListSelector); + return ( ', () => { monitorList: true, serviceLocations: false, }, + syntheticsService: { + loading: false, + }, } as MonitorManagementListState, }; diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/test_now_col.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/test_now_col.tsx index de32c874ae24c..68845067f1275 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/test_now_col.tsx +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/test_now_col.tsx @@ -24,7 +24,11 @@ export const TestNowColumn = ({ const testNowRun = useSelector(testNowRunSelector(configId)); if (!configId) { - return <>--; + return ( + + <>-- + + ); } const testNowClick = () => { @@ -51,6 +55,13 @@ export const TEST_NOW_ARIA_LABEL = i18n.translate('xpack.uptime.monitorList.test defaultMessage: 'CLick to run test now', }); +export const TEST_NOW_AVAILABLE_LABEL = i18n.translate( + 'xpack.uptime.monitorList.testNow.available', + { + defaultMessage: 'Test now is only available for monitors added via Monitor management.', + } +); + export const TEST_NOW_LABEL = i18n.translate('xpack.uptime.monitorList.testNow.label', { defaultMessage: 'Test now', }); diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx index 552256a6aff1a..ee22ad8b38189 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx @@ -38,7 +38,6 @@ import { MonitorTags } from '../../common/monitor_tags'; import { useMonitorHistogram } from './use_monitor_histogram'; import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common'; import { TestNowColumn } from './columns/test_now_col'; -import { useUptimeSettingsContext } from '../../../contexts/uptime_settings_context'; interface Props extends MonitorListProps { pageSize: number; @@ -105,8 +104,6 @@ export const MonitorListComponent: ({ }, {}); }; - const { config } = useUptimeSettingsContext(); - const columns = [ ...[ { @@ -209,19 +206,15 @@ export const MonitorListComponent: ({ /> ), }, - ...(config.ui?.monitorManagement?.enabled - ? [ - { - align: 'center' as const, - field: '', - name: TEST_NOW_COLUMN, - width: '100px', - render: (item: MonitorSummary) => ( - - ), - }, - ] - : []), + { + align: 'center' as const, + field: '', + name: TEST_NOW_COLUMN, + width: '100px', + render: (item: MonitorSummary) => ( + + ), + }, ...(!hideExtraColumns ? [ { diff --git a/x-pack/plugins/uptime/public/contexts/uptime_settings_context.tsx b/x-pack/plugins/uptime/public/contexts/uptime_settings_context.tsx index 67058be9a9d65..4fda00db57bd7 100644 --- a/x-pack/plugins/uptime/public/contexts/uptime_settings_context.tsx +++ b/x-pack/plugins/uptime/public/contexts/uptime_settings_context.tsx @@ -10,7 +10,6 @@ import { UptimeAppProps } from '../apps/uptime_app'; import { CLIENT_DEFAULTS, CONTEXT_DEFAULTS } from '../../common/constants'; import { CommonlyUsedRange } from '../components/common/uptime_date_picker'; import { useGetUrlParams } from '../hooks'; -import { UptimeUiConfig } from '../../common/config'; export interface UptimeSettingsContextValues { basePath: string; @@ -19,7 +18,6 @@ export interface UptimeSettingsContextValues { isApmAvailable: boolean; isInfraAvailable: boolean; isLogsAvailable: boolean; - config: UptimeUiConfig; commonlyUsedRanges?: CommonlyUsedRange[]; isDev?: boolean; } @@ -39,21 +37,13 @@ const defaultContext: UptimeSettingsContextValues = { isApmAvailable: true, isInfraAvailable: true, isLogsAvailable: true, - config: {}, isDev: false, }; export const UptimeSettingsContext = createContext(defaultContext); export const UptimeSettingsContextProvider: React.FC = ({ children, ...props }) => { - const { - basePath, - isApmAvailable, - isInfraAvailable, - isLogsAvailable, - commonlyUsedRanges, - config, - isDev, - } = props; + const { basePath, isApmAvailable, isInfraAvailable, isLogsAvailable, commonlyUsedRanges, isDev } = + props; const { dateRangeStart, dateRangeEnd } = useGetUrlParams(); @@ -65,7 +55,6 @@ export const UptimeSettingsContextProvider: React.FC = ({ childr isInfraAvailable, isLogsAvailable, commonlyUsedRanges, - config, dateRangeStart: dateRangeStart ?? DATE_RANGE_START, dateRangeEnd: dateRangeEnd ?? DATE_RANGE_END, }; @@ -78,7 +67,6 @@ export const UptimeSettingsContextProvider: React.FC = ({ childr dateRangeStart, dateRangeEnd, commonlyUsedRanges, - config, ]); return ; diff --git a/x-pack/plugins/uptime/public/lib/__mocks__/uptime_store.mock.ts b/x-pack/plugins/uptime/public/lib/__mocks__/uptime_store.mock.ts index bc09ef0514ef3..ff8bd8e7f3f09 100644 --- a/x-pack/plugins/uptime/public/lib/__mocks__/uptime_store.mock.ts +++ b/x-pack/plugins/uptime/public/lib/__mocks__/uptime_store.mock.ts @@ -77,6 +77,9 @@ export const mockState: AppState = { monitorList: null, serviceLocations: null, }, + syntheticsService: { + loading: false, + }, }, ml: { mlJob: { diff --git a/x-pack/plugins/uptime/public/pages/monitor_management/service_allowed_wrapper.test.tsx b/x-pack/plugins/uptime/public/pages/monitor_management/service_allowed_wrapper.test.tsx new file mode 100644 index 0000000000000..a8aac213186d3 --- /dev/null +++ b/x-pack/plugins/uptime/public/pages/monitor_management/service_allowed_wrapper.test.tsx @@ -0,0 +1,64 @@ +/* + * 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 React from 'react'; +import { render } from '../../lib/helper/rtl_helpers'; + +import * as allowedHook from '../../components/monitor_management/hooks/use_service_allowed'; +import { ServiceAllowedWrapper } from './service_allowed_wrapper'; + +describe('ServiceAllowedWrapper', () => { + it('renders expected elements for valid props', async () => { + const { findByText } = render( + +
Test text
+
+ ); + + expect(await findByText('Test text')).toBeInTheDocument(); + }); + + it('renders when enabled state is loading', async () => { + jest.spyOn(allowedHook, 'useSyntheticsServiceAllowed').mockReturnValue({ loading: true }); + + const { findByText } = render( + +
Test text
+
+ ); + + expect(await findByText('Loading monitor management')).toBeInTheDocument(); + }); + + it('renders when enabled state is false', async () => { + jest + .spyOn(allowedHook, 'useSyntheticsServiceAllowed') + .mockReturnValue({ loading: false, isAllowed: false }); + + const { findByText } = render( + +
Test text
+
+ ); + + expect(await findByText('Monitor management')).toBeInTheDocument(); + }); + + it('renders when enabled state is true', async () => { + jest + .spyOn(allowedHook, 'useSyntheticsServiceAllowed') + .mockReturnValue({ loading: false, isAllowed: true }); + + const { findByText } = render( + +
Test text
+
+ ); + + expect(await findByText('Test text')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/uptime/public/pages/monitor_management/service_allowed_wrapper.tsx b/x-pack/plugins/uptime/public/pages/monitor_management/service_allowed_wrapper.tsx new file mode 100644 index 0000000000000..3092b8f5f1c3b --- /dev/null +++ b/x-pack/plugins/uptime/public/pages/monitor_management/service_allowed_wrapper.tsx @@ -0,0 +1,66 @@ +/* + * 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 React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiButton, EuiEmptyPrompt, EuiLoadingLogo } from '@elastic/eui'; +import { useSyntheticsServiceAllowed } from '../../components/monitor_management/hooks/use_service_allowed'; + +export const ServiceAllowedWrapper: React.FC = ({ children }) => { + const { isAllowed, loading } = useSyntheticsServiceAllowed(); + + if (loading) { + return ( + } + title={

{LOADING_MONITOR_MANAGEMENT_LABEL}

} + /> + ); + } + + // checking for explicit false + if (isAllowed === false) { + return ( + {MONITOR_MANAGEMENT_LABEL}} + body={

{PUBLIC_BETA_DESCRIPTION}

} + actions={[ + + {REQUEST_ACCESS_LABEL} + , + ]} + /> + ); + } + + return <>{children}; +}; + +const REQUEST_ACCESS_LABEL = i18n.translate('xpack.uptime.monitorManagement.requestAccess', { + defaultMessage: 'Request access', +}); + +const MONITOR_MANAGEMENT_LABEL = i18n.translate('xpack.uptime.monitorManagement.label', { + defaultMessage: 'Monitor management', +}); + +const LOADING_MONITOR_MANAGEMENT_LABEL = i18n.translate( + 'xpack.uptime.monitorManagement.loading.label', + { + defaultMessage: 'Loading monitor management', + } +); + +const PUBLIC_BETA_DESCRIPTION = i18n.translate( + 'xpack.uptime.monitorManagement.publicBetaDescription', + { + defaultMessage: + 'Monitor management is available only for selected public beta users. With public\n' + + 'beta access, you will be able to add HTTP, TCP, ICMP and Browser checks which will\n' + + "run on Elastic's managed synthetics service nodes.", + } +); diff --git a/x-pack/plugins/uptime/public/routes.test.tsx b/x-pack/plugins/uptime/public/routes.test.tsx deleted file mode 100644 index ed4b3bed6cbba..0000000000000 --- a/x-pack/plugins/uptime/public/routes.test.tsx +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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. - */ - -// app.test.js -import { screen } from '@testing-library/react'; -import { render } from './lib/helper/rtl_helpers'; -import { createMemoryHistory } from 'history'; -import React from 'react'; -import * as telemetry from './hooks/use_telemetry'; -import { MONITOR_ADD_ROUTE, MONITOR_EDIT_ROUTE } from '../common/constants'; - -import '@testing-library/jest-dom'; - -import { PageRouter } from './routes'; - -describe('PageRouter', () => { - beforeEach(() => { - jest.spyOn(telemetry, 'useUptimeTelemetry').mockImplementation(() => {}); - }); - it.each([MONITOR_ADD_ROUTE, MONITOR_EDIT_ROUTE])( - 'hides ui monitor management pages when feature flag is not enabled', - (page) => { - const history = createMemoryHistory(); - history.push(page); - render(, { history }); - - expect(screen.getByText(/Page not found/i)).toBeInTheDocument(); - } - ); - - it.each([ - [MONITOR_ADD_ROUTE, 'Add Monitor'], - [MONITOR_EDIT_ROUTE, 'Edit Monitor'], - ])('hides ui monitor management pages when feature flag is not enabled', (page, heading) => { - const history = createMemoryHistory(); - history.push(page); - render(, { - history, - }); - - expect(screen.getByText(heading)).toBeInTheDocument(); - }); -}); diff --git a/x-pack/plugins/uptime/public/routes.tsx b/x-pack/plugins/uptime/public/routes.tsx index e68f25fcbb134..9164cc10050cb 100644 --- a/x-pack/plugins/uptime/public/routes.tsx +++ b/x-pack/plugins/uptime/public/routes.tsx @@ -55,14 +55,9 @@ import { import { UptimePageTemplateComponent } from './apps/uptime_page_template'; import { apiService } from './state/api/utils'; import { useInspectorContext } from '../../observability/public'; -import { UptimeConfig } from '../common/config'; import { AddMonitorBtn } from './components/monitor_management/add_monitor_btn'; -import { useKibana } from '../../../../src/plugins/kibana_react/public'; import { SettingsBottomBar } from './components/settings/settings_bottom_bar'; - -interface PageRouterProps { - config: UptimeConfig; -} +import { ServiceAllowedWrapper } from './pages/monitor_management/service_allowed_wrapper'; type RouteProps = { path: string; @@ -85,7 +80,7 @@ export const MONITORING_OVERVIEW_LABEL = i18n.translate('xpack.uptime.overview.h defaultMessage: 'Monitors', }); -const getRoutes = (config: UptimeConfig, canSave: boolean): RouteProps[] => { +const getRoutes = (): RouteProps[] => { return [ { title: i18n.translate('xpack.uptime.monitorRoute.title', { @@ -190,69 +185,77 @@ const getRoutes = (config: UptimeConfig, canSave: boolean): RouteProps[] => { rightSideItems: [], }, }, - ...(config.ui?.monitorManagement?.enabled - ? [ - { - title: i18n.translate('xpack.uptime.addMonitorRoute.title', { - defaultMessage: 'Add Monitor | {baseTitle}', - values: { baseTitle }, - }), - path: MONITOR_ADD_ROUTE, - component: AddMonitorPage, - dataTestSubj: 'uptimeMonitorAddPage', - telemetryId: UptimePage.MonitorAdd, - pageHeader: { - pageTitle: ( - - ), - }, - bottomBar: , - bottomBarProps: { paddingSize: 'm' as const }, - }, - { - title: i18n.translate('xpack.uptime.editMonitorRoute.title', { - defaultMessage: 'Edit Monitor | {baseTitle}', - values: { baseTitle }, - }), - path: MONITOR_EDIT_ROUTE, - component: EditMonitorPage, - dataTestSubj: 'uptimeMonitorEditPage', - telemetryId: UptimePage.MonitorEdit, - pageHeader: { - pageTitle: ( - - ), - }, - bottomBar: , - bottomBarProps: { paddingSize: 'm' as const }, - }, - { - title: i18n.translate('xpack.uptime.monitorManagementRoute.title', { - defaultMessage: 'Manage Monitors | {baseTitle}', - values: { baseTitle }, - }), - path: MONITOR_MANAGEMENT_ROUTE + '/:type', - component: MonitorManagementPage, - dataTestSubj: 'uptimeMonitorManagementListPage', - telemetryId: UptimePage.MonitorManagement, - pageHeader: { - pageTitle: ( - - ), - rightSideItems: [], - }, - }, - ] - : []), + { + title: i18n.translate('xpack.uptime.addMonitorRoute.title', { + defaultMessage: 'Add Monitor | {baseTitle}', + values: { baseTitle }, + }), + path: MONITOR_ADD_ROUTE, + component: () => ( + + + + ), + dataTestSubj: 'uptimeMonitorAddPage', + telemetryId: UptimePage.MonitorAdd, + pageHeader: { + pageTitle: ( + + ), + }, + bottomBar: , + bottomBarProps: { paddingSize: 'm' as const }, + }, + { + title: i18n.translate('xpack.uptime.editMonitorRoute.title', { + defaultMessage: 'Edit Monitor | {baseTitle}', + values: { baseTitle }, + }), + path: MONITOR_EDIT_ROUTE, + component: () => ( + + + + ), + dataTestSubj: 'uptimeMonitorEditPage', + telemetryId: UptimePage.MonitorEdit, + pageHeader: { + pageTitle: ( + + ), + }, + bottomBar: , + bottomBarProps: { paddingSize: 'm' as const }, + }, + { + title: i18n.translate('xpack.uptime.monitorManagementRoute.title', { + defaultMessage: 'Manage Monitors | {baseTitle}', + values: { baseTitle }, + }), + path: MONITOR_MANAGEMENT_ROUTE + '/:type', + component: () => ( + + + + ), + dataTestSubj: 'uptimeMonitorManagementListPage', + telemetryId: UptimePage.MonitorManagement, + pageHeader: { + pageTitle: ( + + ), + rightSideItems: [], + }, + }, ]; }; @@ -268,10 +271,8 @@ const RouteInit: React.FC> = return null; }; -export const PageRouter: FC = ({ config = {} }) => { - const canSave: boolean = !!useKibana().services?.application?.capabilities.uptime.save; - - const routes = getRoutes(config, canSave); +export const PageRouter: FC = () => { + const routes = getRoutes(); const { addInspectorRequest } = useInspectorContext(); apiService.addInspectorRequest = addInspectorRequest; diff --git a/x-pack/plugins/uptime/public/state/actions/monitor_management.ts b/x-pack/plugins/uptime/public/state/actions/monitor_management.ts index b2c84709279d8..8d61e6bb8204b 100644 --- a/x-pack/plugins/uptime/public/state/actions/monitor_management.ts +++ b/x-pack/plugins/uptime/public/state/actions/monitor_management.ts @@ -11,6 +11,8 @@ import { ServiceLocations, FetchMonitorManagementListQueryArgs, } from '../../../common/runtime_types'; +import { createAsyncAction } from './utils'; +import { SyntheticsServiceAllowed } from '../../../common/types'; export const getMonitors = createAction( 'GET_MONITOR_MANAGEMENT_LIST' @@ -25,3 +27,7 @@ export const getServiceLocationsSuccess = createAction( 'GET_SERVICE_LOCATIONS_LIST_SUCCESS' ); export const getServiceLocationsFailure = createAction('GET_SERVICE_LOCATIONS_LIST_FAILURE'); + +export const getSyntheticsServiceAllowed = createAsyncAction( + 'GET_SYNTHETICS_SERVICE_ALLOWED' +); diff --git a/x-pack/plugins/uptime/public/state/api/monitor_management.ts b/x-pack/plugins/uptime/public/state/api/monitor_management.ts index 00a033ec51b7a..25571caae2e5a 100644 --- a/x-pack/plugins/uptime/public/state/api/monitor_management.ts +++ b/x-pack/plugins/uptime/public/state/api/monitor_management.ts @@ -15,7 +15,7 @@ import { ServiceLocationsApiResponseCodec, ServiceLocationErrors, } from '../../../common/runtime_types'; -import { SyntheticsMonitorSavedObject } from '../../../common/types'; +import { SyntheticsMonitorSavedObject, SyntheticsServiceAllowed } from '../../../common/types'; import { apiService } from './utils'; export const setMonitor = async ({ @@ -78,3 +78,7 @@ export interface TestNowResponse { export const testNowMonitor = async (configId: string): Promise => { return await apiService.get(API_URLS.TRIGGER_MONITOR + `/${configId}`); }; + +export const fetchServiceAllowed = async (): Promise => { + return await apiService.get(API_URLS.SERVICE_ALLOWED); +}; diff --git a/x-pack/plugins/uptime/public/state/effects/index.ts b/x-pack/plugins/uptime/public/state/effects/index.ts index 07b04f8c27c3d..5c61c2ff26d1f 100644 --- a/x-pack/plugins/uptime/public/state/effects/index.ts +++ b/x-pack/plugins/uptime/public/state/effects/index.ts @@ -12,7 +12,10 @@ import { fetchRunNowMonitorEffect, fetchUpdatedMonitorEffect, } from './monitor_list'; -import { fetchMonitorManagementEffect } from './monitor_management'; +import { + fetchMonitorManagementEffect, + fetchSyntheticsServiceAllowedEffect, +} from './monitor_management'; import { fetchMonitorStatusEffect } from './monitor_status'; import { fetchDynamicSettingsEffect, setDynamicSettingsEffect } from './dynamic_settings'; import { fetchPingsEffect, fetchPingHistogramEffect } from './ping'; @@ -48,4 +51,5 @@ export function* rootEffect() { yield fork(generateBlockStatsOnPut); yield fork(pruneBlockCache); yield fork(fetchRunNowMonitorEffect); + yield fork(fetchSyntheticsServiceAllowedEffect); } diff --git a/x-pack/plugins/uptime/public/state/effects/monitor_management.ts b/x-pack/plugins/uptime/public/state/effects/monitor_management.ts index c4ca2a203745c..5839d5d9ca30f 100644 --- a/x-pack/plugins/uptime/public/state/effects/monitor_management.ts +++ b/x-pack/plugins/uptime/public/state/effects/monitor_management.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { takeLatest } from 'redux-saga/effects'; +import { takeLatest, takeLeading } from 'redux-saga/effects'; import { getMonitors, getMonitorsSuccess, @@ -13,8 +13,9 @@ import { getServiceLocations, getServiceLocationsSuccess, getServiceLocationsFailure, + getSyntheticsServiceAllowed, } from '../actions'; -import { fetchMonitorManagementList, fetchServiceLocations } from '../api'; +import { fetchMonitorManagementList, fetchServiceAllowed, fetchServiceLocations } from '../api'; import { fetchEffectFactory } from './fetch_effect'; export function* fetchMonitorManagementEffect() { @@ -31,3 +32,14 @@ export function* fetchMonitorManagementEffect() { ) ); } + +export function* fetchSyntheticsServiceAllowedEffect() { + yield takeLeading( + getSyntheticsServiceAllowed.get, + fetchEffectFactory( + fetchServiceAllowed, + getSyntheticsServiceAllowed.success, + getSyntheticsServiceAllowed.fail + ) + ); +} diff --git a/x-pack/plugins/uptime/public/state/reducers/monitor_management.ts b/x-pack/plugins/uptime/public/state/reducers/monitor_management.ts index 94b1c5dbc945a..17e8677111612 100644 --- a/x-pack/plugins/uptime/public/state/reducers/monitor_management.ts +++ b/x-pack/plugins/uptime/public/state/reducers/monitor_management.ts @@ -14,14 +14,17 @@ import { getServiceLocations, getServiceLocationsSuccess, getServiceLocationsFailure, + getSyntheticsServiceAllowed, } from '../actions'; import { MonitorManagementListResult, ServiceLocations } from '../../../common/runtime_types'; +import { SyntheticsServiceAllowed } from '../../../common/types'; export interface MonitorManagementList { error: Record<'monitorList' | 'serviceLocations', Error | null>; loading: Record<'monitorList' | 'serviceLocations', boolean>; list: MonitorManagementListResult; locations: ServiceLocations; + syntheticsService: { isAllowed?: boolean; loading: boolean }; } export const initialState: MonitorManagementList = { @@ -40,6 +43,9 @@ export const initialState: MonitorManagementList = { monitorList: null, serviceLocations: null, }, + syntheticsService: { + loading: false, + }, }; export const monitorManagementListReducer = createReducer(initialState, (builder) => { @@ -118,5 +124,38 @@ export const monitorManagementListReducer = createReducer(initialState, (builder serviceLocations: action.payload, }, }) + ) + .addCase( + String(getSyntheticsServiceAllowed.get), + (state: WritableDraft) => ({ + ...state, + syntheticsService: { + isAllowed: state.syntheticsService?.isAllowed, + loading: true, + }, + }) + ) + .addCase( + String(getSyntheticsServiceAllowed.success), + ( + state: WritableDraft, + action: PayloadAction + ) => ({ + ...state, + syntheticsService: { + isAllowed: action.payload.serviceAllowed, + loading: false, + }, + }) + ) + .addCase( + String(getSyntheticsServiceAllowed.fail), + (state: WritableDraft, action: PayloadAction) => ({ + ...state, + syntheticsService: { + isAllowed: false, + loading: false, + }, + }) ); }); diff --git a/x-pack/plugins/uptime/public/state/selectors/index.ts b/x-pack/plugins/uptime/public/state/selectors/index.ts index f14699bf73b69..f420648664fef 100644 --- a/x-pack/plugins/uptime/public/state/selectors/index.ts +++ b/x-pack/plugins/uptime/public/state/selectors/index.ts @@ -94,3 +94,6 @@ export const networkEventsSelector = ({ networkEvents }: AppState) => networkEve export const syntheticsSelector = ({ synthetics }: AppState) => synthetics; export const uptimeWriteSelector = (state: AppState) => state; + +export const syntheticsServiceAllowedSelector = (state: AppState) => + state.monitorManagementList.syntheticsService; diff --git a/x-pack/plugins/uptime/server/lib/lib.ts b/x-pack/plugins/uptime/server/lib/lib.ts index 220ac5a3797a4..8b5761900e487 100644 --- a/x-pack/plugins/uptime/server/lib/lib.ts +++ b/x-pack/plugins/uptime/server/lib/lib.ts @@ -60,7 +60,8 @@ export function createUptimeESClient({ baseESClient: esClient, async search( params: TParams, - operationName?: string + operationName?: string, + index?: string ): Promise<{ body: ESSearchResponse }> { let res: any; let esError: any; @@ -68,7 +69,7 @@ export function createUptimeESClient({ savedObjectsClient! ); - const esParams = { index: dynamicSettings!.heartbeatIndices, ...params }; + const esParams = { index: index ?? dynamicSettings!.heartbeatIndices, ...params }; const startTime = process.hrtime(); const startTimeNow = Date.now(); @@ -84,6 +85,7 @@ export function createUptimeESClient({ } const inspectableEsQueries = inspectableEsQueriesMap.get(request!); + if (inspectableEsQueries) { inspectableEsQueries.push( getInspectResponse({ diff --git a/x-pack/plugins/uptime/server/lib/synthetics_service/hydrate_saved_object.ts b/x-pack/plugins/uptime/server/lib/synthetics_service/hydrate_saved_object.ts index f240652b27691..8ee9fbca88561 100644 --- a/x-pack/plugins/uptime/server/lib/synthetics_service/hydrate_saved_object.ts +++ b/x-pack/plugins/uptime/server/lib/synthetics_service/hydrate_saved_object.ts @@ -85,44 +85,48 @@ export const hydrateSavedObjects = async ({ }; const fetchSampleMonitorDocuments = async (esClient: UptimeESClient, configIds: string[]) => { - const data = await esClient.search({ - body: { - query: { - bool: { - filter: [ - { - range: { - '@timestamp': { - gte: 'now-15m', - lt: 'now', + const data = await esClient.search( + { + body: { + query: { + bool: { + filter: [ + { + range: { + '@timestamp': { + gte: 'now-15m', + lt: 'now', + }, }, }, - }, - { - terms: { - config_id: configIds, + { + terms: { + config_id: configIds, + }, }, - }, - { - exists: { - field: 'summary', + { + exists: { + field: 'summary', + }, }, - }, - { - bool: { - minimum_should_match: 1, - should: [{ exists: { field: 'url.full' } }, { exists: { field: 'url.port' } }], + { + bool: { + minimum_should_match: 1, + should: [{ exists: { field: 'url.full' } }, { exists: { field: 'url.port' } }], + }, }, - }, - ], + ], + }, + }, + _source: ['url', 'config_id', '@timestamp'], + collapse: { + field: 'config_id', }, - }, - _source: ['url', 'config_id', '@timestamp'], - collapse: { - field: 'config_id', }, }, - }); + 'getHydrateQuery', + 'synthetics-*' + ); return data.body.hits.hits.map( ({ _source: doc }) => ({ ...(doc as any), timestamp: (doc as any)['@timestamp'] } as Ping) diff --git a/x-pack/plugins/uptime/server/lib/synthetics_service/service_api_client.ts b/x-pack/plugins/uptime/server/lib/synthetics_service/service_api_client.ts index 14c5a2ebb5959..cf27574c09d6f 100644 --- a/x-pack/plugins/uptime/server/lib/synthetics_service/service_api_client.ts +++ b/x-pack/plugins/uptime/server/lib/synthetics_service/service_api_client.ts @@ -85,6 +85,38 @@ export class ServiceAPIClient { return this.callAPI('POST', { ...data, runOnce: true }); } + async checkIfAccountAllowed() { + if (this.authorization) { + // in case username/password is provided, we assume it's always allowed + return true; + } + + const httpsAgent = this.getHttpsAgent(); + + if (this.locations.length > 0 && httpsAgent) { + // get a url from a random location + const url = this.locations[Math.floor(Math.random() * this.locations.length)].url; + + try { + const { data } = await axios({ + method: 'GET', + url: url + '/allowed', + headers: + process.env.NODE_ENV !== 'production' && this.authorization + ? { + Authorization: this.authorization, + } + : undefined, + httpsAgent, + }); + return data.allowed; + } catch (e) { + this.logger.error(e); + } + } + return false; + } + async callAPI( method: 'POST' | 'PUT' | 'DELETE', { monitors: allMonitors, output, runOnce }: ServiceData diff --git a/x-pack/plugins/uptime/server/lib/synthetics_service/synthetics_service.test.ts b/x-pack/plugins/uptime/server/lib/synthetics_service/synthetics_service.test.ts new file mode 100644 index 0000000000000..74c4aa0fca7da --- /dev/null +++ b/x-pack/plugins/uptime/server/lib/synthetics_service/synthetics_service.test.ts @@ -0,0 +1,68 @@ +/* + * 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 { SyntheticsService } from './synthetics_service'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { loggerMock } from './../../../../../../src/core/server/logging/logger.mock'; +import { UptimeServerSetup } from '../adapters'; + +describe('SyntheticsService', () => { + const mockEsClient = { + search: jest.fn(), + }; + + const serverMock: UptimeServerSetup = { + uptimeEsClient: mockEsClient, + authSavedObjectsClient: { + bulkUpdate: jest.fn(), + }, + } as unknown as UptimeServerSetup; + + const logger = loggerMock.create(); + + it('inits properly', async () => { + const service = new SyntheticsService(logger, serverMock, {}); + service.init(); + + expect(service.isAllowed).toEqual(false); + expect(service.locations).toEqual([]); + }); + + it('inits properly with basic auth', async () => { + const service = new SyntheticsService(logger, serverMock, { + username: 'dev', + password: '12345', + }); + + await service.init(); + + expect(service.isAllowed).toEqual(true); + }); + + it('inits properly with locations with dev', async () => { + serverMock.config = { service: { devUrl: 'http://localhost' } }; + const service = new SyntheticsService(logger, serverMock, { + username: 'dev', + password: '12345', + }); + + await service.init(); + + expect(service.isAllowed).toEqual(true); + expect(service.locations).toEqual([ + { + geo: { + lat: 0, + lon: 0, + }, + id: 'localhost', + label: 'Local Synthetics Service', + url: 'http://localhost', + }, + ]); + }); +}); diff --git a/x-pack/plugins/uptime/server/lib/synthetics_service/synthetics_service.ts b/x-pack/plugins/uptime/server/lib/synthetics_service/synthetics_service.ts index 11dcf1973b41c..78a3e0ca70c6d 100644 --- a/x-pack/plugins/uptime/server/lib/synthetics_service/synthetics_service.ts +++ b/x-pack/plugins/uptime/server/lib/synthetics_service/synthetics_service.ts @@ -54,28 +54,25 @@ export class SyntheticsService { private indexTemplateExists?: boolean; private indexTemplateInstalling?: boolean; + public isAllowed: boolean; + constructor(logger: Logger, server: UptimeServerSetup, config: ServiceConfig) { this.logger = logger; this.server = server; this.config = config; + this.isAllowed = false; this.apiClient = new ServiceAPIClient(logger, this.config, this.server.kibanaVersion); this.esHosts = getEsHosts({ config: this.config, cloud: server.cloud }); this.locations = []; - - this.registerServiceLocations(); } - public init() { - // TODO: Figure out fake kibana requests to handle API keys on start up - // getAPIKeyForSyntheticsService({ server: this.server }).then((apiKey) => { - // if (apiKey) { - // this.apiKey = apiKey; - // } - // }); - this.setupIndexTemplates(); + public async init() { + await this.registerServiceLocations(); + + this.isAllowed = await this.apiClient.checkIfAccountAllowed(); } private setupIndexTemplates() { @@ -105,12 +102,15 @@ export class SyntheticsService { } } - public registerServiceLocations() { + public async registerServiceLocations() { const service = this; - getServiceLocations(service.server).then((result) => { + try { + const result = await getServiceLocations(service.server); service.locations = result.locations; service.apiClient.locations = result.locations; - }); + } catch (e) { + this.logger.error(e); + } } public registerSyncTask(taskManager: TaskManagerSetupContract) { @@ -130,10 +130,14 @@ export class SyntheticsService { async run() { const { state } = taskInstance; - service.setupIndexTemplates(); - service.registerServiceLocations(); + await service.registerServiceLocations(); + + service.isAllowed = await service.apiClient.checkIfAccountAllowed(); - await service.pushConfigs(); + if (service.isAllowed) { + service.setupIndexTemplates(); + await service.pushConfigs(); + } return { state }; }, diff --git a/x-pack/plugins/uptime/server/plugin.ts b/x-pack/plugins/uptime/server/plugin.ts index 61272651e1ce2..13c05d0182119 100644 --- a/x-pack/plugins/uptime/server/plugin.ts +++ b/x-pack/plugins/uptime/server/plugin.ts @@ -39,14 +39,11 @@ export class Plugin implements PluginType { private server?: UptimeServerSetup; private syntheticService?: SyntheticsService; private readonly telemetryEventsSender: TelemetryEventsSender; - private readonly isServiceEnabled?: boolean; constructor(initializerContext: PluginInitializerContext) { this.initContext = initializerContext; this.logger = initializerContext.logger.get(); this.telemetryEventsSender = new TelemetryEventsSender(this.logger); - const config = this.initContext.config.get(); - this.isServiceEnabled = config?.ui?.monitorManagement?.enabled && Boolean(config.service); } public setup(core: CoreSetup, plugins: UptimeCorePluginsSetup) { @@ -84,7 +81,7 @@ export class Plugin implements PluginType { isDev: this.initContext.env.mode.dev, } as UptimeServerSetup; - if (this.isServiceEnabled && this.server.config.service) { + if (this.server.config.service) { this.syntheticService = new SyntheticsService( this.logger, this.server, @@ -100,7 +97,7 @@ export class Plugin implements PluginType { registerUptimeSavedObjects( core.savedObjects, plugins.encryptedSavedObjects, - Boolean(this.isServiceEnabled) + Boolean(this.server.config.service) ); KibanaTelemetryAdapter.registerUsageCollector( @@ -114,7 +111,7 @@ export class Plugin implements PluginType { } public start(coreStart: CoreStart, plugins: UptimeCorePluginsStart) { - if (this.isServiceEnabled) { + if (this.server?.config.service) { this.savedObjectsClient = new SavedObjectsClient( coreStart.savedObjects.createInternalRepository([syntheticsServiceApiKey.name]) ); @@ -131,7 +128,7 @@ export class Plugin implements PluginType { this.server.savedObjectsClient = this.savedObjectsClient; } - if (this.isServiceEnabled) { + if (this.server?.config.service) { this.syntheticService?.init(); this.syntheticService?.scheduleSyncTask(plugins.taskManager); if (this.server && this.syntheticService) { diff --git a/x-pack/plugins/uptime/server/rest_api/index.ts b/x-pack/plugins/uptime/server/rest_api/index.ts index 780a67c0941e1..8b0775b6ed31a 100644 --- a/x-pack/plugins/uptime/server/rest_api/index.ts +++ b/x-pack/plugins/uptime/server/rest_api/index.ts @@ -38,6 +38,7 @@ import { editSyntheticsMonitorRoute } from './synthetics_service/edit_monitor'; import { deleteSyntheticsMonitorRoute } from './synthetics_service/delete_monitor'; import { runOnceSyntheticsMonitorRoute } from './synthetics_service/run_once_monitor'; import { testNowMonitorRoute } from './synthetics_service/test_now_monitor'; +import { getServiceAllowedRoute } from './synthetics_service/get_service_allowed'; export * from './types'; export { createRouteWithAuth } from './create_route_with_auth'; @@ -71,4 +72,5 @@ export const restApiRoutes: UMRestApiRouteFactory[] = [ deleteSyntheticsMonitorRoute, runOnceSyntheticsMonitorRoute, testNowMonitorRoute, + getServiceAllowedRoute, ]; diff --git a/x-pack/plugins/uptime/server/rest_api/synthetics_service/get_service_allowed.ts b/x-pack/plugins/uptime/server/rest_api/synthetics_service/get_service_allowed.ts new file mode 100644 index 0000000000000..a7d6a1e0c9882 --- /dev/null +++ b/x-pack/plugins/uptime/server/rest_api/synthetics_service/get_service_allowed.ts @@ -0,0 +1,18 @@ +/* + * 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 { UMRestApiRouteFactory } from '../types'; +import { API_URLS } from '../../../common/constants'; + +export const getServiceAllowedRoute: UMRestApiRouteFactory = () => ({ + method: 'GET', + path: API_URLS.SERVICE_ALLOWED, + validate: {}, + handler: async ({ server }): Promise => { + return { serviceAllowed: server.syntheticsService.isAllowed }; + }, +}); diff --git a/x-pack/plugins/uptime/server/rest_api/uptime_route_wrapper.ts b/x-pack/plugins/uptime/server/rest_api/uptime_route_wrapper.ts index 60ba60087382a..450997c7c110d 100644 --- a/x-pack/plugins/uptime/server/rest_api/uptime_route_wrapper.ts +++ b/x-pack/plugins/uptime/server/rest_api/uptime_route_wrapper.ts @@ -23,7 +23,7 @@ export const uptimeRouteWrapper: UMKibanaRouteWrapper = (uptimeRoute, server) => handler: async (context, request, response) => { const { client: esClient } = context.core.elasticsearch; let savedObjectsClient: SavedObjectsClientContract; - if (server.config?.ui?.monitorManagement?.enabled) { + if (server.config?.service) { savedObjectsClient = context.core.savedObjects.getClient({ includedHiddenTypes: [syntheticsServiceApiKey.name], }); diff --git a/x-pack/test/api_integration/config.ts b/x-pack/test/api_integration/config.ts index af355695f3ed8..203b0b4d53dbf 100644 --- a/x-pack/test/api_integration/config.ts +++ b/x-pack/test/api_integration/config.ts @@ -35,7 +35,6 @@ export async function getApiIntegrationConfig({ readConfigFile }: FtrConfigProvi '--xpack.ruleRegistry.write.enabled=true', '--xpack.ruleRegistry.write.enabled=true', '--xpack.ruleRegistry.write.cache.enabled=false', - '--xpack.uptime.ui.monitorManagement.enabled=true', '--xpack.uptime.service.password=test', '--xpack.uptime.service.username=localKibanaIntegrationTestsUser', `--xpack.securitySolution.enableExperimental=${JSON.stringify(['ruleRegistryEnabled'])}`,