From e73d14e5c807ff050bb703d2e83ca9893583e757 Mon Sep 17 00:00:00 2001 From: Igor Zaytsev Date: Wed, 15 Jul 2020 07:09:56 -0400 Subject: [PATCH] Added a case for Alerting if security/ssl is disabled --- x-pack/plugins/monitoring/kibana.json | 3 +- .../monitoring/public/services/clusters.js | 8 +-- .../elasticsearch/verify_alerting_security.ts | 62 +++++++++++++++++++ x-pack/plugins/monitoring/server/plugin.ts | 2 + .../server/routes/api/v1/alerts/enable.ts | 18 ++++-- x-pack/plugins/monitoring/server/types.ts | 2 + 6 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 x-pack/plugins/monitoring/server/lib/elasticsearch/verify_alerting_security.ts diff --git a/x-pack/plugins/monitoring/kibana.json b/x-pack/plugins/monitoring/kibana.json index 3b9e60124b0343..2b8756ea0cb46d 100644 --- a/x-pack/plugins/monitoring/kibana.json +++ b/x-pack/plugins/monitoring/kibana.json @@ -11,7 +11,8 @@ "kibanaLegacy", "triggers_actions_ui", "alerts", - "actions" + "actions", + "encryptedSavedObjects" ], "optionalPlugins": ["infra", "telemetryCollectionManager", "usageCollection", "home", "cloud"], "server": true, diff --git a/x-pack/plugins/monitoring/public/services/clusters.js b/x-pack/plugins/monitoring/public/services/clusters.js index f3eadcaf9831b7..dbe2e33ffae75f 100644 --- a/x-pack/plugins/monitoring/public/services/clusters.js +++ b/x-pack/plugins/monitoring/public/services/clusters.js @@ -55,10 +55,10 @@ export function monitoringClustersProvider($injector) { } function ensureAlertsEnabled() { - return $http.post('../api/monitoring/v1/alerts/enable', {}).catch((err) => { - const Private = $injector.get('Private'); - const ajaxErrorHandlers = Private(ajaxErrorHandlersProvider); - return ajaxErrorHandlers(err); + return $http.post('../api/monitoring/v1/alerts/enable', {}).catch(() => { + /** + * Ignoring for now, but should really indicate what is the cause + */ }); } diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/verify_alerting_security.ts b/x-pack/plugins/monitoring/server/lib/elasticsearch/verify_alerting_security.ts new file mode 100644 index 00000000000000..16731a80141c66 --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/verify_alerting_security.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { RequestHandlerContext } from 'kibana/server'; + +import { EncryptedSavedObjectsPluginSetup } from '../../../../encrypted_saved_objects/server'; + +export interface AlertingFrameworkHealth { + isSufficientlySecure: boolean; + hasPermanentEncryptionKey: boolean; +} + +export interface XPackUsageSecurity { + security?: { + enabled?: boolean; + ssl?: { + http?: { + enabled?: boolean; + }; + }; + }; +} + +export class AlertingSecurity { + private static _encryptedSavedObjects: EncryptedSavedObjectsPluginSetup; + + public static readonly init = (encryptedSavedObjects: EncryptedSavedObjectsPluginSetup) => { + AlertingSecurity._encryptedSavedObjects = encryptedSavedObjects; + }; + + public static readonly getSecurityHealth = async ( + context: RequestHandlerContext + ): Promise => { + const { + security: { + enabled: isSecurityEnabled = false, + ssl: { http: { enabled: isTLSEnabled = false } = {} } = {}, + } = {}, + }: XPackUsageSecurity = await context.core.elasticsearch.legacy.client.callAsInternalUser( + 'transport.request', + { + method: 'GET', + path: '/_xpack/usage', + } + ); + + if (!AlertingSecurity._encryptedSavedObjects) { + throw Error( + 'AlertingSecurity.init() needs to be set before using AlertingSecurity.getSecurityHealth' + ); + } + + return { + isSufficientlySecure: !isSecurityEnabled || (isSecurityEnabled && isTLSEnabled), + hasPermanentEncryptionKey: !AlertingSecurity._encryptedSavedObjects + .usingEphemeralEncryptionKey, + }; + }; +} diff --git a/x-pack/plugins/monitoring/server/plugin.ts b/x-pack/plugins/monitoring/server/plugin.ts index 5f358badde4012..7620b616a363a1 100644 --- a/x-pack/plugins/monitoring/server/plugin.ts +++ b/x-pack/plugins/monitoring/server/plugin.ts @@ -33,6 +33,7 @@ import { requireUIRoutes } from './routes'; import { initBulkUploader } from './kibana_monitoring'; // @ts-ignore import { initInfraSource } from './lib/logs/init_infra_source'; +import { AlertingSecurity } from './lib/elasticsearch/verify_alerting_security'; import { instantiateClient } from './es_client/instantiate_client'; import { registerCollectors } from './kibana_monitoring/collectors'; import { registerMonitoringCollection } from './telemetry_collection'; @@ -79,6 +80,7 @@ export class Plugin { } async setup(core: CoreSetup, plugins: PluginsSetup) { + AlertingSecurity.init(plugins.encryptedSavedObjects); const [config, legacyConfig] = await combineLatest([ this.initializerContext.config .create>() diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/alerts/enable.ts b/x-pack/plugins/monitoring/server/routes/api/v1/alerts/enable.ts index 1d83644fce756e..99d24ccf75e2bb 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/alerts/enable.ts +++ b/x-pack/plugins/monitoring/server/routes/api/v1/alerts/enable.ts @@ -10,23 +10,33 @@ import { AlertsFactory } from '../../../../alerts'; import { RouteDependencies } from '../../../../types'; import { ALERT_ACTION_TYPE_LOG } from '../../../../../common/constants'; import { ActionResult } from '../../../../../../actions/common'; -// import { fetchDefaultEmailAddress } from '../../../../lib/alerts/fetch_default_email_address'; +import { AlertingSecurity } from '../../../../lib/elasticsearch/verify_alerting_security'; const DEFAULT_SERVER_LOG_NAME = 'Monitoring: Write to Kibana log'; -export function enableAlertsRoute(server: any, npRoute: RouteDependencies) { +export function enableAlertsRoute(_server: unknown, npRoute: RouteDependencies) { npRoute.router.post( { path: '/api/monitoring/v1/alerts/enable', options: { tags: ['access:monitoring'] }, validate: false, }, - async (context, request, response) => { + async (context, _request, response) => { try { + const { + isSufficientlySecure, + hasPermanentEncryptionKey, + } = await AlertingSecurity.getSecurityHealth(context); const alertsClient = context.alerting?.getAlertsClient(); const actionsClient = context.actions?.getActionsClient(); const types = context.actions?.listTypes(); - if (!alertsClient || !actionsClient || !types) { + if ( + !alertsClient || + !actionsClient || + !types || + !isSufficientlySecure || + !hasPermanentEncryptionKey + ) { return response.notFound(); } diff --git a/x-pack/plugins/monitoring/server/types.ts b/x-pack/plugins/monitoring/server/types.ts index 0c346c8082475b..5fbb469950390e 100644 --- a/x-pack/plugins/monitoring/server/types.ts +++ b/x-pack/plugins/monitoring/server/types.ts @@ -16,6 +16,7 @@ import { import { InfraPluginSetup } from '../../infra/server'; import { LicensingPluginSetup } from '../../licensing/server'; import { PluginSetupContract as FeaturesPluginSetupContract } from '../../features/server'; +import { EncryptedSavedObjectsPluginSetup } from '../../encrypted_saved_objects/server'; export interface MonitoringLicenseService { refresh: () => Promise; @@ -36,6 +37,7 @@ export interface LegacyAPI { } export interface PluginsSetup { + encryptedSavedObjects: EncryptedSavedObjectsPluginSetup; telemetryCollectionManager?: TelemetryCollectionManagerPluginSetup; usageCollection?: UsageCollectionSetup; licensing: LicensingPluginSetup;