Skip to content

Commit

Permalink
[Monitoring] Added a case for Alerting if security/ssl is disabled (#…
Browse files Browse the repository at this point in the history
…71846) (#72295)

* Added a case for Alerting if security/ssl is disabled

* Code feedback

* Fixed types

Co-authored-by: igoristic <igor.zaytsev.dev@gmail.com>
  • Loading branch information
chrisronline and igoristic authored Jul 17, 2020
1 parent 31c425e commit d3073f3
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 6 deletions.
3 changes: 2 additions & 1 deletion x-pack/plugins/monitoring/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"kibanaLegacy",
"triggers_actions_ui",
"alerts",
"actions"
"actions",
"encryptedSavedObjects"
],
"optionalPlugins": ["infra", "telemetryCollectionManager", "usageCollection", "home", "cloud"],
"server": true,
Expand Down
137 changes: 137 additions & 0 deletions x-pack/plugins/monitoring/public/alerts/lib/security_toasts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* 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 React from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiSpacer, EuiLink, EuiCode, EuiText } from '@elastic/eui';
import { Legacy } from '../../legacy_shims';
import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public';

export interface AlertingFrameworkHealth {
isSufficientlySecure: boolean;
hasPermanentEncryptionKey: boolean;
}

const showTlsAndEncryptionError = () => {
const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = Legacy.shims.docLinks;

Legacy.shims.toastNotifications.addWarning({
title: toMountPoint(
<FormattedMessage
id="xpack.monitoring.healthCheck.tlsAndEncryptionErrorTitle"
defaultMessage="Additional setup required"
/>
),
text: toMountPoint(
<div>
<p>
{i18n.translate('xpack.monitoring.healthCheck.tlsAndEncryptionError', {
defaultMessage: `You must enable Transport Layer Security between Kibana and Elasticsearch
and configure an encryption key in your kibana.yml file to use the Alerting feature.`,
})}
</p>
<EuiSpacer />
<EuiLink
href={`${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/alert-action-settings-kb.html#general-alert-action-settings`}
external
target="_blank"
>
{i18n.translate('xpack.monitoring.healthCheck.encryptionErrorAction', {
defaultMessage: 'Learn how.',
})}
</EuiLink>
</div>
),
});
};

const showEncryptionError = () => {
const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = Legacy.shims.docLinks;

Legacy.shims.toastNotifications.addWarning(
{
title: toMountPoint(
<FormattedMessage
id="xpack.monitoring.healthCheck.encryptionErrorTitle"
defaultMessage="You must set an encryption key"
/>
),
text: toMountPoint(
<div role="banner">
{i18n.translate('xpack.monitoring.healthCheck.encryptionErrorBeforeKey', {
defaultMessage: 'To create an alert, set a value for ',
})}
<EuiText size="xs">
<EuiCode>{'xpack.encryptedSavedObjects.encryptionKey'}</EuiCode>
</EuiText>
{i18n.translate('xpack.monitoring.healthCheck.encryptionErrorAfterKey', {
defaultMessage: ' in your kibana.yml file. ',
})}
<EuiLink
href={`${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/alert-action-settings-kb.html#general-alert-action-settings`}
external
target="_blank"
>
{i18n.translate('xpack.monitoring.healthCheck.encryptionErrorAction', {
defaultMessage: 'Learn how.',
})}
</EuiLink>
</div>
),
},
{}
);
};

const showTlsError = () => {
const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = Legacy.shims.docLinks;

Legacy.shims.toastNotifications.addWarning({
title: toMountPoint(
<FormattedMessage
id="xpack.monitoring.healthCheck.tlsErrorTitle"
defaultMessage="You must enable Transport Layer Security"
/>
),
text: toMountPoint(
<div role="banner">
{i18n.translate('xpack.monitoring.healthCheck.tlsError', {
defaultMessage:
'Alerting relies on API keys, which require TLS between Elasticsearch and Kibana. ',
})}
<EuiLink
href={`${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/configuring-tls.html`}
external
target="_blank"
>
{i18n.translate('xpack.monitoring.healthCheck.tlsErrorAction', {
defaultMessage: 'Learn how to enable TLS.',
})}
</EuiLink>
</div>
),
});
};

export const showSecurityToast = (alertingHealth: AlertingFrameworkHealth) => {
const { isSufficientlySecure, hasPermanentEncryptionKey } = alertingHealth;
if (
Array.isArray(alertingHealth) ||
(!alertingHealth.hasOwnProperty('isSufficientlySecure') &&
!alertingHealth.hasOwnProperty('hasPermanentEncryptionKey'))
) {
return;
}

if (!isSufficientlySecure && !hasPermanentEncryptionKey) {
showTlsAndEncryptionError();
} else if (!isSufficientlySecure) {
showTlsError();
} else if (!hasPermanentEncryptionKey) {
showEncryptionError();
}
};
4 changes: 3 additions & 1 deletion x-pack/plugins/monitoring/public/services/clusters.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { ajaxErrorHandlersProvider } from '../lib/ajax_error_handler';
import { Legacy } from '../legacy_shims';
import { STANDALONE_CLUSTER_CLUSTER_UUID } from '../../common/constants';
import { showSecurityToast } from '../alerts/lib/security_toasts';

function formatClusters(clusters) {
return clusters.map(formatCluster);
Expand Down Expand Up @@ -66,7 +67,8 @@ export function monitoringClustersProvider($injector) {
return getClusters().then((clusters) => {
if (clusters.length) {
return ensureAlertsEnabled()
.then(() => {
.then(({ data }) => {
showSecurityToast(data);
once = true;
return clusters;
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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 {
public static readonly getSecurityHealth = async (
context: RequestHandlerContext,
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup
): Promise<AlertingFrameworkHealth> => {
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',
}
);

return {
isSufficientlySecure: !isSecurityEnabled || (isSecurityEnabled && isTLSEnabled),
hasPermanentEncryptionKey: !encryptedSavedObjects.usingEphemeralEncryptionKey,
};
};
}
1 change: 1 addition & 0 deletions x-pack/plugins/monitoring/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ export class Plugin {
requireUIRoutes(this.monitoringCore, {
router,
licenseService: this.licenseService,
encryptedSavedObjects: plugins.encryptedSavedObjects,
});
initInfraSource(config, plugins.infra);
}
Expand Down
25 changes: 21 additions & 4 deletions x-pack/plugins/monitoring/server/routes/api/v1/alerts/enable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,36 @@ 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',
validate: false,
},
async (context, request, response) => {
async (context, _request, response) => {
try {
const alerts = AlertsFactory.getAll().filter((a) => a.isEnabled(npRoute.licenseService));

if (alerts.length) {
const {
isSufficientlySecure,
hasPermanentEncryptionKey,
} = await AlertingSecurity.getSecurityHealth(context, npRoute.encryptedSavedObjects);

if (!isSufficientlySecure || !hasPermanentEncryptionKey) {
return response.ok({
body: {
isSufficientlySecure,
hasPermanentEncryptionKey,
},
});
}
}

const alertsClient = context.alerting?.getAlertsClient();
const actionsClient = context.actions?.getActionsClient();
const types = context.actions?.listTypes();
Expand Down Expand Up @@ -57,7 +75,6 @@ export function enableAlertsRoute(server: any, npRoute: RouteDependencies) {
},
];

const alerts = AlertsFactory.getAll().filter((a) => a.isEnabled(npRoute.licenseService));
const createdAlerts = await Promise.all(
alerts.map(
async (alert) => await alert.createIfDoesNotExist(alertsClient, actionsClient, actions)
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/monitoring/server/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<any>;
Expand All @@ -36,6 +37,7 @@ export interface LegacyAPI {
}

export interface PluginsSetup {
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup;
telemetryCollectionManager?: TelemetryCollectionManagerPluginSetup;
usageCollection?: UsageCollectionSetup;
licensing: LicensingPluginSetup;
Expand All @@ -56,6 +58,7 @@ export interface MonitoringCoreConfig {
export interface RouteDependencies {
router: IRouter;
licenseService: MonitoringLicenseService;
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup;
}

export interface MonitoringCore {
Expand Down

0 comments on commit d3073f3

Please sign in to comment.