Skip to content

Commit

Permalink
[Response Ops][Alerting] HTTP Version health API (elastic#196690)
Browse files Browse the repository at this point in the history
## Summary

Closes elastic#195181
Closes elastic#195182

OAS descriptions and HTTP version for `GET /api/alerting/_health`

(cherry picked from commit c1ac722)
  • Loading branch information
jcger committed Oct 18, 2024
1 parent 10a9161 commit b809809
Show file tree
Hide file tree
Showing 12 changed files with 167 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* 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.
*/

export { healthFrameworkResponseSchema } from './schemas/latest';
export type { HealthFrameworkResponse } from './types/latest';

export {
healthFrameworkResponseBodySchema as healthFrameworkResponseBodySchemaV1,
healthFrameworkResponseSchema as healthFrameworkResponseSchemaV1,
} from './schemas/v1';
export type { HealthFrameworkResponseBody as HealthFrameworkResponseBodyV1 } from './types/v1';
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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.
*/

export * from './v1';
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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { schema } from '@kbn/config-schema';

const alertingFrameworkHealthSchemaObject = {
status: schema.oneOf([schema.literal('ok'), schema.literal('warn'), schema.literal('error')]),
timestamp: schema.string(),
};

export const healthFrameworkResponseBodySchema = schema.object({
is_sufficiently_secure: schema.boolean({
meta: {
description: 'If false, security is enabled but TLS is not.',
},
}),
has_permanent_encryption_key: schema.boolean({
meta: {
description: 'If false, the encryption key is not set',
},
}),
alerting_framework_health: schema.object(
{
decryption_health: schema.object(alertingFrameworkHealthSchemaObject, {
meta: { description: 'The timestamp and status of the alert decryption.' },
}),
execution_health: schema.object(alertingFrameworkHealthSchemaObject, {
meta: { description: 'The timestamp and status of the alert execution.' },
}),
read_health: schema.object(alertingFrameworkHealthSchemaObject, {
meta: { description: 'The timestamp and status of the alert reading events.' },
}),
},
{
meta: {
description:
'Three substates identify the health of the alerting framework: decryptionHealth, executionHealth, and readHealth.',
},
}
),
});

export const healthFrameworkResponseSchema = schema.object({
body: healthFrameworkResponseBodySchema,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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.
*/

export * from './v1';
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* 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 type { TypeOf } from '@kbn/config-schema';

import { healthFrameworkResponseBodySchemaV1, healthFrameworkResponseSchemaV1 } from '..';

export type HealthFrameworkResponseBody = TypeOf<typeof healthFrameworkResponseBodySchemaV1>;
export type HealthFrameworkResponse = TypeOf<typeof healthFrameworkResponseSchemaV1>;
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@
import { healthRoute } from './health';
import { httpServiceMock } from '@kbn/core/server/mocks';
import { HealthStatus } from '@kbn/alerting-types';
import { mockHandlerArguments } from './_mock_handler_arguments';
import { verifyApiAccess } from '../lib/license_api_access';
import { licenseStateMock } from '../lib/license_state.mock';
import { mockHandlerArguments } from '../../../_mock_handler_arguments';
import { verifyApiAccess } from '../../../../lib/license_api_access';
import { licenseStateMock } from '../../../../lib/license_state.mock';
import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks';
import { rulesClientMock } from '../rules_client.mock';
import { alertsMock } from '../mocks';
import { RecoveredActionGroup } from '../../common';
import { RegistryAlertTypeWithAuth } from '../authorization';
import { rulesClientMock } from '../../../../rules_client.mock';
import { alertsMock } from '../../../../mocks';
import { RecoveredActionGroup } from '../../../../../common';
import { RegistryAlertTypeWithAuth } from '../../../../authorization';

const rulesClient = rulesClientMock.create();

jest.mock('../lib/license_api_access', () => ({
jest.mock('../../../../lib/license_api_access', () => ({
verifyApiAccess: jest.fn(),
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,16 @@

import { IRouter } from '@kbn/core/server';
import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server';
import { ILicenseState } from '../lib';
import { RewriteResponseCase, verifyAccessAndContext } from './lib';
import { healthFrameworkResponseSchemaV1 } from '../../../../../common/routes/framework/apis/health';
import { ILicenseState } from '../../../../lib';
import { verifyAccessAndContext } from '../../../lib';
import {
AlertingRequestHandlerContext,
BASE_ALERTING_API_PATH,
AlertingFrameworkHealth,
} from '../types';
import { getSecurityHealth } from '../lib/get_security_health';

const rewriteBodyRes: RewriteResponseCase<AlertingFrameworkHealth> = ({
isSufficientlySecure,
hasPermanentEncryptionKey,
alertingFrameworkHealth,
...rest
}) => ({
...rest,
is_sufficiently_secure: isSufficientlySecure,
has_permanent_encryption_key: hasPermanentEncryptionKey,
alerting_framework_health: {
decryption_health: alertingFrameworkHealth.decryptionHealth,
execution_health: alertingFrameworkHealth.executionHealth,
read_health: alertingFrameworkHealth.readHealth,
},
});
} from '../../../../types';
import { getSecurityHealth } from '../../../../lib/get_security_health';
import { transformHealthBodyResponse } from './transforms/transform_health_response/v1';

export const healthRoute = (
router: IRouter<AlertingRequestHandlerContext>,
Expand All @@ -45,7 +31,18 @@ export const healthRoute = (
summary: `Get the alerting framework health`,
tags: ['oas-tag:alerting'],
},
validate: false,
validate: {
request: {},
response: {
200: {
body: () => healthFrameworkResponseSchemaV1,
description: 'Indicates a successful call.',
},
401: {
description: 'Authorization information is missing or invalid.',
},
},
},
},
router.handleLegacyErrors(
verifyAccessAndContext(licenseState, async function (context, req, res) {
Expand All @@ -68,7 +65,7 @@ export const healthRoute = (
};

return res.ok({
body: rewriteBodyRes(frameworkHealth),
body: transformHealthBodyResponse(frameworkHealth),
});
} else {
return res.forbidden({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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.
*/

export { healthRoute } from './health';
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* 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.
*/

export { transformHealthBodyResponse } from './transform_health_response/latest';
export { transformHealthBodyResponse as transformHealthBodyResponseV1 } from './transform_health_response/v1';
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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.
*/

export * from './v1';
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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 { AlertingFrameworkHealth } from '../../../../../../types';
import type { HealthFrameworkResponseBodyV1 } from '../../../../../../../common/routes/framework/apis/health';

export const transformHealthBodyResponse = (
frameworkHealth: AlertingFrameworkHealth
): HealthFrameworkResponseBodyV1 => ({
is_sufficiently_secure: frameworkHealth.isSufficientlySecure,
has_permanent_encryption_key: frameworkHealth.hasPermanentEncryptionKey,
alerting_framework_health: {
decryption_health: frameworkHealth.alertingFrameworkHealth.decryptionHealth,
execution_health: frameworkHealth.alertingFrameworkHealth.executionHealth,
read_health: frameworkHealth.alertingFrameworkHealth.readHealth,
},
});
2 changes: 1 addition & 1 deletion x-pack/plugins/alerting/server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { getGlobalExecutionKPIRoute } from './get_global_execution_kpi';
import { getActionErrorLogRoute } from './get_action_error_log';
import { getRuleExecutionKPIRoute } from './get_rule_execution_kpi';
import { getRuleStateRoute } from './get_rule_state';
import { healthRoute } from './health';
import { healthRoute } from './framework/apis/health';
import { resolveRuleRoute } from './rule/apis/resolve';
import { ruleTypesRoute } from './rule/apis/list_types/rule_types';
import { muteAllRuleRoute } from './rule/apis/mute_all/mute_all_rule';
Expand Down

0 comments on commit b809809

Please sign in to comment.