mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
## Summary This PR has breadth, but not depth. This adds 3 new `eslint` rules. The first two protect against the use of code generated from strings (`eval` and friends), which will not work client-side due to our CSP, and is not something we wish to support server-side. The last rule aims to prevent a subtle class of bugs, and to defend against a subset of prototype pollution exploits: - `no-new-func` to be compliant with our CSP, and to prevent code execution from strings server-side: https://eslint.org/docs/latest/rules/no-new-func - `no-implied-eval` to be compliant with our CSP, and to prevent code execution from strings server-side: https://eslint.org/docs/latest/rules/no-implied-eval. Note that this function implies that it prevents no-new-func, but I don't see [test cases](https://github.com/eslint/eslint/blob/main/tests/lib/rules/no-implied-eval.js) covering this behavior, so I think we should play it safe and enable both rules. - `no-prototype-builtins` to prevent accessing shadowed properties: https://eslint.org/docs/latest/rules/no-prototype-builtins In order to be compliant with `no-prototype-builtins`, I've migrated all usages and variants of `Object.hasOwnProperty` to use the newer [`Object.hasOwn`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn).
62 lines
2 KiB
TypeScript
62 lines
2 KiB
TypeScript
/*
|
|
* 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 and the Server Side Public License, v 1; you may not use this file except
|
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
* Side Public License, v 1.
|
|
*/
|
|
|
|
import { Logger } from '@kbn/core/server';
|
|
import { IntegrationCategory, INTEGRATION_CATEGORY_DISPLAY, CustomIntegration } from '../common';
|
|
|
|
function isAddable(integration: CustomIntegration): boolean {
|
|
return !!integration.categories.length && !integration.eprOverlap;
|
|
}
|
|
|
|
function isReplacement(integration: CustomIntegration): boolean {
|
|
return !!integration.categories.length && !!integration.eprOverlap;
|
|
}
|
|
|
|
export class CustomIntegrationRegistry {
|
|
private readonly _integrations: CustomIntegration[];
|
|
private readonly _logger: Logger;
|
|
private readonly _isDev: boolean;
|
|
|
|
constructor(logger: Logger, isDev: boolean) {
|
|
this._integrations = [];
|
|
this._logger = logger;
|
|
this._isDev = isDev;
|
|
}
|
|
|
|
registerCustomIntegration(customIntegration: CustomIntegration) {
|
|
if (
|
|
this._integrations.some((integration: CustomIntegration) => {
|
|
return integration.id === customIntegration.id;
|
|
})
|
|
) {
|
|
const message = `Integration with id=${customIntegration.id} already exists.`;
|
|
if (this._isDev) {
|
|
this._logger.error(message);
|
|
} else {
|
|
this._logger.debug(message);
|
|
}
|
|
return;
|
|
}
|
|
|
|
const allowedCategories: IntegrationCategory[] = (customIntegration.categories ?? []).filter(
|
|
(category) => {
|
|
return Object.hasOwn(INTEGRATION_CATEGORY_DISPLAY, category);
|
|
}
|
|
) as IntegrationCategory[];
|
|
|
|
this._integrations.push({ ...customIntegration, categories: allowedCategories });
|
|
}
|
|
|
|
getAppendCustomIntegrations(): CustomIntegration[] {
|
|
return this._integrations.filter(isAddable);
|
|
}
|
|
|
|
getReplacementCustomIntegrations(): CustomIntegration[] {
|
|
return this._integrations.filter(isReplacement);
|
|
}
|
|
}
|