diff --git a/x-pack/legacy/plugins/reporting/common/constants.ts b/x-pack/legacy/plugins/reporting/common/constants.ts index e602d5fc608d335..92f01ee78a2aa9f 100644 --- a/x-pack/legacy/plugins/reporting/common/constants.ts +++ b/x-pack/legacy/plugins/reporting/common/constants.ts @@ -9,7 +9,7 @@ export const PLUGIN_ID = 'reporting'; export const BROWSER_TYPE = 'chromium'; export const JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY = - 'xpack.reporting.jobCompletionNotifications'; + 'xpack.reporting.jobCompletionNotifications'; // for public - outdated? export const API_BASE_URL = '/api/reporting'; // "Generation URL" from share menu export const API_BASE_URL_V1 = '/api/reporting/v1'; // diff --git a/x-pack/legacy/plugins/reporting/config.ts b/x-pack/legacy/plugins/reporting/config.ts deleted file mode 100644 index 34fc1f452fbc060..000000000000000 --- a/x-pack/legacy/plugins/reporting/config.ts +++ /dev/null @@ -1,171 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { BROWSER_TYPE } from './common/constants'; -// @ts-ignore untyped module -import { config as appConfig } from './server/config/config'; -import { getDefaultChromiumSandboxDisabled } from './server/browsers'; - -export async function config(Joi: any) { - return Joi.object({ - enabled: Joi.boolean().default(true), - kibanaServer: Joi.object({ - protocol: Joi.string().valid(['http', 'https']), - hostname: Joi.string().invalid('0'), - port: Joi.number().integer(), - }).default(), - queue: Joi.object({ - indexInterval: Joi.string().default('week'), - pollEnabled: Joi.boolean().default(true), - pollInterval: Joi.number() - .integer() - .default(3000), - pollIntervalErrorMultiplier: Joi.number() - .integer() - .default(10), - timeout: Joi.number() - .integer() - .default(120000), - }).default(), - capture: Joi.object({ - networkPolicy: Joi.object({ - enabled: Joi.boolean().default(true), - rules: Joi.array() - .items( - Joi.object({ - allow: Joi.boolean().required(), - protocol: Joi.string(), - host: Joi.string(), - }) - ) - .default([ - { allow: true, protocol: 'http:' }, - { allow: true, protocol: 'https:' }, - { allow: true, protocol: 'ws:' }, - { allow: true, protocol: 'wss:' }, - { allow: true, protocol: 'data:' }, - { allow: false }, // Default action is to deny! - ]), - }).default(), - zoom: Joi.number() - .integer() - .default(2), - viewport: Joi.object({ - width: Joi.number() - .integer() - .default(1950), - height: Joi.number() - .integer() - .default(1200), - }).default(), - timeout: Joi.number() - .integer() - .default(20000), // deprecated - loadDelay: Joi.number() - .integer() - .default(3000), - settleTime: Joi.number() - .integer() - .default(1000), // deprecated - concurrency: Joi.number() - .integer() - .default(appConfig.concurrency), // deprecated - browser: Joi.object({ - type: Joi.any() - .valid(BROWSER_TYPE) - .default(BROWSER_TYPE), - autoDownload: Joi.boolean().when('$dist', { - is: true, - then: Joi.default(false), - otherwise: Joi.default(true), - }), - chromium: Joi.object({ - inspect: Joi.boolean() - .when('$dev', { - is: false, - then: Joi.valid(false), - else: Joi.default(false), - }) - .default(), - disableSandbox: Joi.boolean().default(await getDefaultChromiumSandboxDisabled()), - proxy: Joi.object({ - enabled: Joi.boolean().default(false), - server: Joi.string() - .uri({ scheme: ['http', 'https'] }) - .when('enabled', { - is: Joi.valid(false), - then: Joi.valid(null), - else: Joi.required(), - }), - bypass: Joi.array() - .items(Joi.string().regex(/^[^\s]+$/)) - .when('enabled', { - is: Joi.valid(false), - then: Joi.valid(null), - else: Joi.default([]), - }), - }).default(), - maxScreenshotDimension: Joi.number() - .integer() - .default(1950), - }).default(), - }).default(), - maxAttempts: Joi.number() - .integer() - .greater(0) - .when('$dist', { - is: true, - then: Joi.default(3), - otherwise: Joi.default(1), - }) - .default(), - }).default(), - csv: Joi.object({ - checkForFormulas: Joi.boolean().default(true), - enablePanelActionDownload: Joi.boolean().default(true), - maxSizeBytes: Joi.number() - .integer() - .default(1024 * 1024 * 10), // bytes in a kB * kB in a mB * 10 - scroll: Joi.object({ - duration: Joi.string() - .regex(/^[0-9]+(d|h|m|s|ms|micros|nanos)$/, { name: 'DurationString' }) - .default('30s'), - size: Joi.number() - .integer() - .default(500), - }).default(), - }).default(), - encryptionKey: Joi.when(Joi.ref('$dist'), { - is: true, - then: Joi.string(), - otherwise: Joi.string().default('a'.repeat(32)), - }), - roles: Joi.object({ - allow: Joi.array() - .items(Joi.string()) - .default(['reporting_user']), - }).default(), - index: Joi.string().default('.reporting'), - poll: Joi.object({ - jobCompletionNotifier: Joi.object({ - interval: Joi.number() - .integer() - .default(10000), - intervalErrorMultiplier: Joi.number() - .integer() - .default(5), - }).default(), - jobsRefresh: Joi.object({ - interval: Joi.number() - .integer() - .default(5000), - intervalErrorMultiplier: Joi.number() - .integer() - .default(5), - }).default(), - }).default(), - }).default(); -} diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.test.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.test.ts index 070bdb4314af9c9..20a683217ab514e 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.test.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.test.ts @@ -17,7 +17,7 @@ beforeEach(() => { describe('conditions', () => { test(`uses hostname from reporting config if set`, async () => { const settings: any = { - 'xpack.reporting.kibanaServer.hostname': 'custom-hostname', + 'kibanaServer.hostname': 'custom-hostname', }; mockServer = createMockServer({ settings }); @@ -34,7 +34,7 @@ describe('conditions', () => { }); expect(conditionalHeaders.conditions.hostname).toEqual( - mockServer.config().get('xpack.reporting.kibanaServer.hostname') + mockServer.config().get('kibanaServer.hostname') ); }); @@ -55,7 +55,7 @@ describe('conditions', () => { test(`uses port from reporting config if set`, async () => { const settings = { - 'xpack.reporting.kibanaServer.port': 443, + 'kibanaServer.port': 443, }; mockServer = createMockServer({ settings }); @@ -72,7 +72,7 @@ describe('conditions', () => { }); expect(conditionalHeaders.conditions.port).toEqual( - mockServer.config().get('xpack.reporting.kibanaServer.port') + mockServer.config().get('kibanaServer.port') ); }); @@ -110,7 +110,7 @@ describe('conditions', () => { test(`uses protocol from reporting config if set`, async () => { const settings = { - 'xpack.reporting.kibanaServer.protocol': 'https', + 'kibanaServer.protocol': 'https', }; mockServer = createMockServer({ settings }); @@ -127,7 +127,7 @@ describe('conditions', () => { }); expect(conditionalHeaders.conditions.protocol).toEqual( - mockServer.config().get('xpack.reporting.kibanaServer.protocol') + mockServer.config().get('kibanaServer.protocol') ); }); @@ -211,9 +211,9 @@ describe('config formatting', () => { expect(conditionalHeaders.conditions.hostname).toEqual('cool-hostname'); }); - test(`lowercases xpack.reporting.kibanaServer.hostname`, async () => { + test(`lowercases kibanaServer.hostname`, async () => { mockServer = createMockServer({ - settings: { 'xpack.reporting.kibanaServer.hostname': 'GREAT-HOSTNAME' }, + settings: { 'kibanaServer.hostname': 'GREAT-HOSTNAME' }, }); const conditionalHeaders = await getConditionalHeaders({ job: { diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.ts index 975060a8052f072..ef1f2c1459a59e8 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.ts @@ -15,12 +15,14 @@ export const getConditionalHeaders = ({ filteredHeaders: Record; }) => { const config = server.config(); + const kbnConfig = server.kbnConfig(); + // TODO: set defaults in Reporting config setup instead of handle conditions here const [hostname, port, basePath, protocol] = [ - config.get('xpack.reporting.kibanaServer.hostname') || config.get('server.host'), - config.get('xpack.reporting.kibanaServer.port') || config.get('server.port'), - config.get('server.basePath'), - config.get('xpack.reporting.kibanaServer.protocol') || server.info.protocol, - ] as [string, number, string, string]; + config.get('kibanaServer.hostname') || kbnConfig.get('server.host'), + config.get('kibanaServer.port') || kbnConfig.get('server.port'), + kbnConfig.get('server.basePath'), + config.get('kibanaServer.protocol') || kbnConfig.get('server.protocol'), + ]; const conditionalHeaders: ConditionalHeaders = { headers: filteredHeaders, diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts index ca64d8632dbfebc..76b6fb5cde21971 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts @@ -31,12 +31,14 @@ export function getFullUrls({ job: JobDocPayloadPDF | JobDocPayloadPNG; }) { const config = server.config(); + const kbnConfig = server.kbnConfig(); + // TODO: set defaults in Reporting config setup instead of handle conditions here const getAbsoluteUrl = getAbsoluteUrlFactory({ - defaultBasePath: config.get('server.basePath'), - protocol: config.get('xpack.reporting.kibanaServer.protocol') || server.info.protocol, - hostname: config.get('xpack.reporting.kibanaServer.hostname') || config.get('server.host'), - port: config.get('xpack.reporting.kibanaServer.port') || config.get('server.port'), + defaultBasePath: kbnConfig.get('server.basePath'), + protocol: config.get('kibanaServer.protocol') || kbnConfig.get('server.protocol'), + hostname: config.get('kibanaServer.hostname') || kbnConfig.get('server.host'), + port: config.get('kibanaServer.port') || kbnConfig.get('server.port'), }); // PDF and PNG job params put in the url differently diff --git a/x-pack/legacy/plugins/reporting/export_types/common/layouts/print_layout.ts b/x-pack/legacy/plugins/reporting/export_types/common/layouts/print_layout.ts index 44361181e32628f..89ee5d82f173582 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/layouts/print_layout.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/layouts/print_layout.ts @@ -22,7 +22,7 @@ export class PrintLayout extends Layout { constructor(server: ServerFacade) { super(LayoutTypes.PRINT); - this.captureConfig = server.config().get('xpack.reporting.capture'); + this.captureConfig = server.config().get('capture'); } public getCssOverridesPath() { diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts index b83021d5e38dd85..c1f6afd673e994e 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts @@ -24,7 +24,7 @@ export function screenshotsObservableFactory( browserDriverFactory: HeadlessChromiumDriverFactory ) { const config = server.config(); - const captureConfig: CaptureConfig = config.get('xpack.reporting.capture'); + const captureConfig: CaptureConfig = config.get('capture'); return function screenshotsObservable({ logger, diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js index 6109db8542764da..86281b7aae239e0 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js @@ -102,15 +102,15 @@ describe('CSV Execute Job', function() { }; mockServer .config() - .get.withArgs('xpack.reporting.encryptionKey') + .get.withArgs('encryptionKey') .returns(encryptionKey); mockServer .config() - .get.withArgs('xpack.reporting.csv.maxSizeBytes') + .get.withArgs('csv.maxSizeBytes') .returns(1024 * 1000); // 1mB mockServer .config() - .get.withArgs('xpack.reporting.csv.scroll') + .get.withArgs('csv.scroll') .returns({}); }); @@ -361,7 +361,7 @@ describe('CSV Execute Job', function() { it('returns `csv_contains_formulas` when cells contain formulas', async function() { mockServer .config() - .get.withArgs('xpack.reporting.csv.checkForFormulas') + .get.withArgs('csv.checkForFormulas') .returns(true); callWithRequestStub.onFirstCall().returns({ hits: { @@ -389,7 +389,7 @@ describe('CSV Execute Job', function() { it('returns warnings when headings contain formulas', async function() { mockServer .config() - .get.withArgs('xpack.reporting.csv.checkForFormulas') + .get.withArgs('csv.checkForFormulas') .returns(true); callWithRequestStub.onFirstCall().returns({ hits: { @@ -417,7 +417,7 @@ describe('CSV Execute Job', function() { it('returns no warnings when cells have no formulas', async function() { mockServer .config() - .get.withArgs('xpack.reporting.csv.checkForFormulas') + .get.withArgs('csv.checkForFormulas') .returns(true); callWithRequestStub.onFirstCall().returns({ hits: { @@ -445,7 +445,7 @@ describe('CSV Execute Job', function() { it('returns no warnings when configured not to', async () => { mockServer .config() - .get.withArgs('xpack.reporting.csv.checkForFormulas') + .get.withArgs('csv.checkForFormulas') .returns(false); callWithRequestStub.onFirstCall().returns({ hits: { @@ -830,7 +830,7 @@ describe('CSV Execute Job', function() { beforeEach(async function() { mockServer .config() - .get.withArgs('xpack.reporting.csv.maxSizeBytes') + .get.withArgs('csv.maxSizeBytes') .returns(1); const executeJob = executeJobFactory(mockServer, mockLogger); @@ -863,7 +863,7 @@ describe('CSV Execute Job', function() { beforeEach(async function() { mockServer .config() - .get.withArgs('xpack.reporting.csv.maxSizeBytes') + .get.withArgs('csv.maxSizeBytes') .returns(9); const executeJob = executeJobFactory(mockServer, mockLogger); @@ -896,7 +896,7 @@ describe('CSV Execute Job', function() { beforeEach(async function() { mockServer .config() - .get.withArgs('xpack.reporting.csv.maxSizeBytes') + .get.withArgs('csv.maxSizeBytes') .returns(9); callWithRequestStub.onFirstCall().returns({ @@ -937,7 +937,7 @@ describe('CSV Execute Job', function() { beforeEach(async function() { mockServer .config() - .get.withArgs('xpack.reporting.csv.maxSizeBytes') + .get.withArgs('csv.maxSizeBytes') .returns(18); callWithRequestStub.onFirstCall().returns({ @@ -977,7 +977,7 @@ describe('CSV Execute Job', function() { const scrollDuration = 'test'; mockServer .config() - .get.withArgs('xpack.reporting.csv.scroll') + .get.withArgs('csv.scroll') .returns({ duration: scrollDuration }); callWithRequestStub.onFirstCall().returns({ @@ -1006,7 +1006,7 @@ describe('CSV Execute Job', function() { const scrollSize = 100; mockServer .config() - .get.withArgs('xpack.reporting.csv.scroll') + .get.withArgs('csv.scroll') .returns({ size: scrollSize }); callWithRequestStub.onFirstCall().resolves({ @@ -1035,7 +1035,7 @@ describe('CSV Execute Job', function() { const scrollDuration = 'test'; mockServer .config() - .get.withArgs('xpack.reporting.csv.scroll') + .get.withArgs('csv.scroll') .returns({ duration: scrollDuration }); callWithRequestStub.onFirstCall().resolves({ diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts index d8b4cdd9718eaa7..1f17abbcae800c7 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts @@ -26,8 +26,9 @@ export const executeJobFactory: ExecuteJobFactory { - const fieldFormats = (await server.fieldFormatServiceFactory(uiConfig)) as FieldFormats; + const fieldFormats = (await server.fieldFormatServiceFactory(uiConfig)) as FieldFormats; // FIXME for New Platform return fieldFormatMapFactory(indexPatternSavedObject, fieldFormats); })(), (async () => { @@ -129,9 +130,9 @@ export const executeJobFactory: ExecuteJobFactory { config = { - 'xpack.reporting.encryptionKey': 'testencryptionkey', + encryptionKey: 'testencryptionkey', 'server.basePath': '/sbp', 'server.host': 'localhost', 'server.port': 5601, diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js index cb038561cd8bc52..feb0f8383938aa4 100644 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js +++ b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js @@ -21,7 +21,7 @@ let config; let mockServer; beforeEach(() => { config = { - 'xpack.reporting.encryptionKey': 'testencryptionkey', + encryptionKey: 'testencryptionkey', 'server.basePath': '/sbp', 'server.host': 'localhost', 'server.port': 5601, diff --git a/x-pack/legacy/plugins/reporting/index.test.js b/x-pack/legacy/plugins/reporting/index.test.js deleted file mode 100644 index 0d9a717bd7d816b..000000000000000 --- a/x-pack/legacy/plugins/reporting/index.test.js +++ /dev/null @@ -1,34 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { reporting } from './index'; -import { getConfigSchema } from '../../../test_utils'; - -// The snapshot records the number of cpus available -// to make the snapshot deterministic `os.cpus` needs to be mocked -// but the other members on `os` must remain untouched -jest.mock('os', () => { - const os = jest.requireActual('os'); - os.cpus = () => [{}, {}, {}, {}]; - return os; -}); - -// eslint-disable-next-line jest/valid-describe -const describeWithContext = describe.each([ - [{ dev: false, dist: false }], - [{ dev: true, dist: false }], - [{ dev: false, dist: true }], - [{ dev: true, dist: true }], -]); - -describeWithContext('config schema with context %j', context => { - it('produces correct config', async () => { - const schema = await getConfigSchema(reporting); - const value = await schema.validate({}, { context }); - value.capture.browser.chromium.disableSandbox = ''; - await expect(value).toMatchSnapshot(); - }); -}); diff --git a/x-pack/legacy/plugins/reporting/index.ts b/x-pack/legacy/plugins/reporting/index.ts index 3a60fc143c019cf..bd0d41266a2c01e 100644 --- a/x-pack/legacy/plugins/reporting/index.ts +++ b/x-pack/legacy/plugins/reporting/index.ts @@ -4,30 +4,25 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resolve } from 'path'; -import { i18n } from '@kbn/i18n'; import { Legacy } from 'kibana'; -import { PLUGIN_ID, UI_SETTINGS_CUSTOM_PDF_LOGO } from './common/constants'; -import { ReportingConfigOptions, ReportingPluginSpecOptions } from './types.d'; -import { config as reportingConfig } from './config'; +import { get } from 'lodash'; +import { resolve } from 'path'; +import { take } from 'rxjs/operators'; +import { PluginsSetup } from '../../../plugins/reporting/server'; +import { PLUGIN_ID } from './common/constants'; import { LegacySetup, ReportingPlugin, - ReportingSetupDeps, reportingPluginFactory, + ReportingSetupDeps, } from './server/plugin'; - -const kbToBase64Length = (kb: number) => { - return Math.floor((kb * 1024 * 8) / 6); -}; +import { ReportingPluginSpecOptions } from './types.d'; export const reporting = (kibana: any) => { return new kibana.Plugin({ id: PLUGIN_ID, - configPrefix: 'xpack.reporting', publicDir: resolve(__dirname, 'public'), require: ['kibana', 'elasticsearch', 'xpack_main'], - config: reportingConfig, uiExports: { shareContextMenuExtensions: [ @@ -37,32 +32,6 @@ export const reporting = (kibana: any) => { embeddableActions: ['plugins/reporting/panel_actions/get_csv_panel_action'], home: ['plugins/reporting/register_feature'], managementSections: ['plugins/reporting/views/management'], - injectDefaultVars(server: Legacy.Server, options?: ReportingConfigOptions) { - const config = server.config(); - return { - reportingPollConfig: options ? options.poll : {}, - enablePanelActionDownload: config.get('xpack.reporting.csv.enablePanelActionDownload'), - }; - }, - uiSettingDefaults: { - [UI_SETTINGS_CUSTOM_PDF_LOGO]: { - name: i18n.translate('xpack.reporting.pdfFooterImageLabel', { - defaultMessage: 'PDF footer image', - }), - value: null, - description: i18n.translate('xpack.reporting.pdfFooterImageDescription', { - defaultMessage: `Custom image to use in the PDF's footer`, - }), - type: 'image', - validation: { - maxSize: { - length: kbToBase64Length(200), - description: '200 kB', - }, - }, - category: [PLUGIN_ID], - }, - }, }, async init(server: Legacy.Server) { @@ -70,8 +39,32 @@ export const reporting = (kibana: any) => { const pluginsSetup: ReportingSetupDeps = { usageCollection: server.newPlatform.setup.plugins.usageCollection, }; + + const { + __legacy: { config$ }, + } = server.newPlatform.setup.plugins.reporting as PluginsSetup; + const currentConfig = await config$.pipe(take(1)).toPromise(); + const config = server.config(); + const globalConfig = { + path: { + data: config.get('path.data'), + }, + server: { + basePath: config.get('server.basePath'), + host: config.get('server.basePath'), + name: config.get('server.basePath'), + port: config.get('server.basePath'), + uuid: config.get('server.basePath'), + protocol: server.info.protocol, + }, + }; const __LEGACY: LegacySetup = { - config: server.config, + config: () => ({ + get: (key: string) => get(currentConfig, key), + }), + kbnConfig: () => ({ + get: (key: string) => get(globalConfig, key), + }), info: server.info, route: server.route.bind(server), plugins: { @@ -90,13 +83,6 @@ export const reporting = (kibana: any) => { await plugin.setup(coreSetup, pluginsSetup); }, - deprecations({ unused }: any) { - return [ - unused('capture.concurrency'), - unused('capture.timeout'), - unused('capture.settleTime'), - unused('kibanaApp'), - ]; - }, + deprecations({ unused }: any) {}, // NOTE: none for 8.0 } as ReportingPluginSpecOptions); }; diff --git a/x-pack/legacy/plugins/reporting/log_configuration.ts b/x-pack/legacy/plugins/reporting/log_configuration.ts index b07475df6304ff3..027fb43695a6a53 100644 --- a/x-pack/legacy/plugins/reporting/log_configuration.ts +++ b/x-pack/legacy/plugins/reporting/log_configuration.ts @@ -13,16 +13,13 @@ const getos = promisify(getosSync); export async function logConfiguration(server: ServerFacade, logger: Logger) { const config = server.config(); - const browserType = config.get('xpack.reporting.capture.browser.type'); + const browserType = config.get('capture.browser.type'); logger.debug(`Browser type: ${browserType}`); - if (browserType === 'chromium') { - logger.debug( - `Chromium sandbox disabled: ${config.get( - 'xpack.reporting.capture.browser.chromium.disableSandbox' - )}` - ); - } + // NOTE: we don't need to log this if we never automatically disable sandbox + logger.debug( + `Chromium sandbox disabled: ${config.get('capture.browser.chromium.disableSandbox')}` + ); const os = await getos(); const { os: osName, dist, release } = os as LinuxOs; diff --git a/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts b/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts index 128df4d318c764a..dd5d4381924534b 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts @@ -16,14 +16,15 @@ export async function createBrowserDriverFactory( logger: Logger ): Promise { const config = server.config(); + const kbnConfig = server.kbnConfig(); - const dataDir: string = config.get('path.data'); - const captureConfig: CaptureConfig = config.get('xpack.reporting.capture'); + const dataDir = kbnConfig.get('path.data'); + const captureConfig: CaptureConfig = config.get('capture'); const browserType = captureConfig.browser.type; const browserAutoDownload = captureConfig.browser.autoDownload; const browserConfig = captureConfig.browser[BROWSER_TYPE]; const networkPolicy = captureConfig.networkPolicy; - const reportingTimeout: number = config.get('xpack.reporting.queue.timeout'); + const reportingTimeout = config.get('queue.timeout'); if (browserConfig.disableSandbox) { logger.warning(`Enabling the Chromium sandbox provides an additional layer of protection.`); diff --git a/x-pack/legacy/plugins/reporting/server/config/config.js b/x-pack/legacy/plugins/reporting/server/config/config.js deleted file mode 100644 index 08e4db464b0034a..000000000000000 --- a/x-pack/legacy/plugins/reporting/server/config/config.js +++ /dev/null @@ -1,21 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { cpus } from 'os'; - -const defaultCPUCount = 2; - -function cpuCount() { - try { - return cpus().length; - } catch (e) { - return defaultCPUCount; - } -} - -export const config = { - concurrency: cpuCount(), -}; diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts b/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts index 05b760c0c3bd6c9..6f3b1baa2ffe433 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts @@ -26,8 +26,8 @@ export function createQueueFactory( logger: Logger, { exportTypesRegistry, browserDriverFactory }: CreateQueueFactoryOpts ): Esqueue { - const queueConfig: QueueConfig = server.config().get('xpack.reporting.queue'); - const index = server.config().get('xpack.reporting.index'); + const queueConfig: QueueConfig = server.config().get('queue'); + const index = server.config().get('index'); const queueOptions = { interval: queueConfig.indexInterval, @@ -47,6 +47,7 @@ export function createQueueFactory( }); createWorker(queue); } else { + // TODO i18n logger.info( 'xpack.reporting.queue.pollEnabled is set to false. This Kibana instance ' + 'will not poll for idle jobs to claim and execute. Make sure another ' + diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts b/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts index 6a5c93db32376a9..8d49f4ddf2a0c4d 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts @@ -14,7 +14,7 @@ import { Esqueue } from './esqueue'; import { ClientMock } from './esqueue/__tests__/fixtures/legacy_elasticsearch'; const configGetStub = sinon.stub(); -configGetStub.withArgs('xpack.reporting.queue').returns({ +configGetStub.withArgs('queue').returns({ pollInterval: 3300, pollIntervalErrorMultiplier: 10, }); diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts b/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts index 67869016a250be0..87860ec1bdb3d87 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts @@ -34,9 +34,10 @@ export function createWorkerFactory( ) { type JobDocPayloadType = JobDocPayload; const config = server.config(); - const queueConfig: QueueConfig = config.get('xpack.reporting.queue'); - const kibanaName: string = config.get('server.name'); - const kibanaId: string = config.get('server.uuid'); + const kbnConfig = server.kbnConfig(); + const queueConfig: QueueConfig = config.get('queue'); + const kibanaName = kbnConfig.get('server.name'); + const kibanaId = kbnConfig.get('server.uuid'); // Once more document types are added, this will need to be passed in return function createWorker(queue: ESQueueInstance) { diff --git a/x-pack/legacy/plugins/reporting/server/lib/crypto.ts b/x-pack/legacy/plugins/reporting/server/lib/crypto.ts index dbc01fc947f8b6b..383d0d2e27451e9 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/crypto.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/crypto.ts @@ -9,7 +9,7 @@ import { oncePerServer } from './once_per_server'; import { ServerFacade } from '../../types'; function cryptoFn(server: ServerFacade) { - const encryptionKey = server.config().get('xpack.reporting.encryptionKey'); + const encryptionKey = server.config().get('encryptionKey'); return nodeCrypto({ encryptionKey }); } diff --git a/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts b/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts index 14c57fa35dcf4ea..08cbef173357d6e 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts @@ -40,10 +40,10 @@ export function enqueueJobFactory( ): EnqueueJobFn { const logger = parentLogger.clone(['queue-job']); const config = server.config(); - const captureConfig: CaptureConfig = config.get('xpack.reporting.capture'); + const captureConfig: CaptureConfig = config.get('capture'); const browserType = captureConfig.browser.type; const maxAttempts = captureConfig.maxAttempts; - const queueConfig: QueueConfig = config.get('xpack.reporting.queue'); + const queueConfig: QueueConfig = config.get('queue'); return async function enqueueJob( exportTypeId: string, diff --git a/x-pack/legacy/plugins/reporting/server/lib/esqueue/helpers/index_timestamp.js b/x-pack/legacy/plugins/reporting/server/lib/esqueue/helpers/index_timestamp.js index 6cdbe8f968f75f0..37031691aa4ac8b 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/esqueue/helpers/index_timestamp.js +++ b/x-pack/legacy/plugins/reporting/server/lib/esqueue/helpers/index_timestamp.js @@ -6,6 +6,7 @@ import moment from 'moment'; +// FIXME use moment durations export const intervals = ['year', 'month', 'week', 'day', 'hour', 'minute']; export function indexTimestamp(intervalStr, separator = '-') { diff --git a/x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts b/x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts index 0c16f780c34acda..d6720b7704ad510 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts @@ -35,7 +35,7 @@ interface CountAggResult { } export function jobsQueryFactory(server: ServerFacade) { - const index = server.config().get('xpack.reporting.index'); + const index = server.config().get('index'); // @ts-ignore `errors` does not exist on type Cluster const { callWithInternalUser, errors: esErrors } = server.plugins.elasticsearch.getCluster( 'admin' diff --git a/x-pack/legacy/plugins/reporting/server/lib/validate/__tests__/validate_encryption_key.js b/x-pack/legacy/plugins/reporting/server/lib/validate/__tests__/validate_encryption_key.js deleted file mode 100644 index 10980f702d84937..000000000000000 --- a/x-pack/legacy/plugins/reporting/server/lib/validate/__tests__/validate_encryption_key.js +++ /dev/null @@ -1,34 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import sinon from 'sinon'; -import { validateEncryptionKey } from '../validate_encryption_key'; - -describe('Reporting: Validate config', () => { - const logger = { - warning: sinon.spy(), - }; - - beforeEach(() => { - logger.warning.resetHistory(); - }); - - [undefined, null].forEach(value => { - it(`should log a warning and set xpack.reporting.encryptionKey if encryptionKey is ${value}`, () => { - const config = { - get: sinon.stub().returns(value), - set: sinon.stub(), - }; - - expect(() => validateEncryptionKey({ config: () => config }, logger)).not.to.throwError(); - - sinon.assert.calledWith(config.set, 'xpack.reporting.encryptionKey'); - sinon.assert.calledWithMatch(logger.warning, /Generating a random key/); - sinon.assert.calledWithMatch(logger.warning, /please set xpack.reporting.encryptionKey/); - }); - }); -}); diff --git a/x-pack/legacy/plugins/reporting/server/lib/validate/__tests__/validate_server_host.ts b/x-pack/legacy/plugins/reporting/server/lib/validate/__tests__/validate_server_host.ts deleted file mode 100644 index 04f998fd3e5a5d2..000000000000000 --- a/x-pack/legacy/plugins/reporting/server/lib/validate/__tests__/validate_server_host.ts +++ /dev/null @@ -1,30 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import sinon from 'sinon'; -import { ServerFacade } from '../../../../types'; -import { validateServerHost } from '../validate_server_host'; - -const configKey = 'xpack.reporting.kibanaServer.hostname'; - -describe('Reporting: Validate server host setting', () => { - it(`should log a warning and set ${configKey} if server.host is "0"`, () => { - const getStub = sinon.stub(); - getStub.withArgs('server.host').returns('0'); - getStub.withArgs(configKey).returns(undefined); - const config = { - get: getStub, - set: sinon.stub(), - }; - - expect(() => - validateServerHost(({ config: () => config } as unknown) as ServerFacade) - ).to.throwError(); - - sinon.assert.calledWith(config.set, configKey); - }); -}); diff --git a/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts b/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts index 79a64bd82d0228f..39cb7ea9e72b9d0 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts @@ -8,9 +8,7 @@ import { i18n } from '@kbn/i18n'; import { ServerFacade, Logger } from '../../../types'; import { HeadlessChromiumDriverFactory } from '../../browsers/chromium/driver_factory'; import { validateBrowser } from './validate_browser'; -import { validateEncryptionKey } from './validate_encryption_key'; import { validateMaxContentLength } from './validate_max_content_length'; -import { validateServerHost } from './validate_server_host'; export async function runValidations( server: ServerFacade, @@ -20,9 +18,7 @@ export async function runValidations( try { await Promise.all([ validateBrowser(server, browserFactory, logger), - validateEncryptionKey(server, logger), validateMaxContentLength(server, logger), - validateServerHost(server), ]); logger.debug( i18n.translate('xpack.reporting.selfCheck.ok', { diff --git a/x-pack/legacy/plugins/reporting/server/lib/validate/validate_encryption_key.ts b/x-pack/legacy/plugins/reporting/server/lib/validate/validate_encryption_key.ts deleted file mode 100644 index e0af94cbdc29cff..000000000000000 --- a/x-pack/legacy/plugins/reporting/server/lib/validate/validate_encryption_key.ts +++ /dev/null @@ -1,31 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; -import crypto from 'crypto'; -import { ServerFacade, Logger } from '../../../types'; - -export function validateEncryptionKey(serverFacade: ServerFacade, logger: Logger) { - const config = serverFacade.config(); - - const encryptionKey = config.get('xpack.reporting.encryptionKey'); - if (encryptionKey == null) { - // TODO this should simply throw an error and let the handler conver it to a warning mesasge. See validateServerHost. - logger.warning( - i18n.translate('xpack.reporting.selfCheckEncryptionKey.warning', { - defaultMessage: - `Generating a random key for {setting}. To prevent pending reports ` + - `from failing on restart, please set {setting} in kibana.yml`, - values: { - setting: 'xpack.reporting.encryptionKey', - }, - }) - ); - - // @ts-ignore: No set() method on KibanaConfig, just get() and has() - config.set('xpack.reporting.encryptionKey', crypto.randomBytes(16).toString('hex')); // update config in memory to contain a usable encryption key - } -} diff --git a/x-pack/legacy/plugins/reporting/server/lib/validate/validate_max_content_length.ts b/x-pack/legacy/plugins/reporting/server/lib/validate/validate_max_content_length.ts index f91cd40bfd3c733..9b4f43dd60c227a 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/validate/validate_max_content_length.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/validate/validate_max_content_length.ts @@ -7,7 +7,7 @@ import numeral from '@elastic/numeral'; import { defaults, get } from 'lodash'; import { Logger, ServerFacade } from '../../../types'; -const KIBANA_MAX_SIZE_BYTES_PATH = 'xpack.reporting.csv.maxSizeBytes'; +const KIBANA_MAX_SIZE_BYTES_PATH = 'csv.maxSizeBytes'; const ES_MAX_SIZE_BYTES_PATH = 'http.max_content_length'; export async function validateMaxContentLength(server: ServerFacade, logger: Logger) { diff --git a/x-pack/legacy/plugins/reporting/server/lib/validate/validate_server_host.ts b/x-pack/legacy/plugins/reporting/server/lib/validate/validate_server_host.ts deleted file mode 100644 index f4f4d61246b6ae5..000000000000000 --- a/x-pack/legacy/plugins/reporting/server/lib/validate/validate_server_host.ts +++ /dev/null @@ -1,27 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { ServerFacade } from '../../../types'; - -const configKey = 'xpack.reporting.kibanaServer.hostname'; - -export function validateServerHost(serverFacade: ServerFacade) { - const config = serverFacade.config(); - - const serverHost = config.get('server.host'); - const reportingKibanaHostName = config.get(configKey); - - if (!reportingKibanaHostName && serverHost === '0') { - // @ts-ignore: No set() method on KibanaConfig, just get() and has() - config.set(configKey, '0.0.0.0'); // update config in memory to allow Reporting to work - - throw new Error( - `Found 'server.host: "0"' in settings. This is incompatible with Reporting. ` + - `To enable Reporting to work, '${configKey}: 0.0.0.0' is being automatically to the configuration. ` + - `You can change to 'server.host: 0.0.0.0' or add '${configKey}: 0.0.0.0' in kibana.yml to prevent this message.` - ); - } -} diff --git a/x-pack/legacy/plugins/reporting/server/plugin.ts b/x-pack/legacy/plugins/reporting/server/plugin.ts index b0dc56dd8d8d0e6..92628cdf9d8145a 100644 --- a/x-pack/legacy/plugins/reporting/server/plugin.ts +++ b/x-pack/legacy/plugins/reporting/server/plugin.ts @@ -34,8 +34,16 @@ export type ReportingStartDeps = object; type LegacyPlugins = Legacy.Server['plugins']; +interface ReportingConfigService { + get: (key: string) => any; +} +interface LegacyConfigService { + get: (key: string) => any; +} + export interface LegacySetup { - config: Legacy.Server['config']; + config: () => ReportingConfigService; + kbnConfig: () => LegacyConfigService; info: Legacy.Server['info']; plugins: { elasticsearch: LegacyPlugins['elasticsearch']; diff --git a/x-pack/legacy/plugins/reporting/server/routes/generation.ts b/x-pack/legacy/plugins/reporting/server/routes/generation.ts index 2a3102d0dd1590b..978ddc2452a63f7 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generation.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generation.ts @@ -27,7 +27,8 @@ export function registerJobGenerationRoutes( logger: Logger ) { const config = server.config(); - const DOWNLOAD_BASE_URL = config.get('server.basePath') + `${API_BASE_URL}/jobs/download`; + const kbnConfig = server.kbnConfig(); + const DOWNLOAD_BASE_URL = kbnConfig.get('server.basePath') + `${API_BASE_URL}/jobs/download`; // @ts-ignore TODO const { errors: esErrors } = server.plugins.elasticsearch.getCluster('admin'); @@ -76,7 +77,7 @@ export function registerJobGenerationRoutes( registerGenerateFromJobParams(server, handler, handleError, logger); // Register beta panel-action download-related API's - if (config.get('xpack.reporting.csv.enablePanelActionDownload')) { + if (config.get('csv.enablePanelActionDownload')) { registerGenerateCsvFromSavedObject(server, handler, handleError, logger); registerGenerateCsvFromSavedObjectImmediate(server, logger); } diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.test.js b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.test.js index 841f753f0c09b4b..c82f220ed81f114 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.test.js +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.test.js @@ -100,7 +100,7 @@ describe('authorized_user_pre_routing', function() { it(`should return with boom forbidden when security is enabled but user doesn't have allowed role`, async function() { const mockServer = createMockServer({ user: { roles: [] }, - config: { 'xpack.reporting.roles.allow': ['.reporting_user'] }, + config: { 'roles.allow': ['.reporting_user'] }, }); const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer, getMockLogger()); @@ -113,7 +113,7 @@ describe('authorized_user_pre_routing', function() { const user = { roles: ['.reporting_user', 'something_else'] }; const mockServer = createMockServer({ user, - config: { 'xpack.reporting.roles.allow': ['.reporting_user'] }, + config: { 'roles.allow': ['.reporting_user'] }, }); const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer, getMockLogger()); @@ -125,7 +125,7 @@ describe('authorized_user_pre_routing', function() { const user = { roles: ['superuser', 'something_else'] }; const mockServer = createMockServer({ user, - config: { 'xpack.reporting.roles.allow': [] }, + config: { 'roles.allow': [] }, }); const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer, getMockLogger()); diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts index 906f266290a4215..8183b30ec269988 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts @@ -44,10 +44,7 @@ export const authorizedUserPreRoutingFactory = function authorizedUserPreRouting return Boom.unauthorized(`Sorry, you aren't authenticated`); } - const authorizedRoles = [ - superuserRole, - ...(config.get('xpack.reporting.roles.allow') as string[]), - ]; + const authorizedRoles = [superuserRole, ...(config.get('roles.allow') as string[])]; if (!user.roles.find(role => authorizedRoles.includes(role))) { return Boom.forbidden(`Sorry, you don't have access to Reporting`); } diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts index 1c0566100e19775..ef68bb56e6469ef 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts @@ -22,9 +22,15 @@ interface ICustomHeaders { type ExportTypeType = ExportTypeDefinition; +interface ErrorFromPayload { + message: string; + reason: string | null; +} + +// A camelCase version of JobDocOutput interface Payload { statusCode: number; - content: any; + content: string | Buffer | ErrorFromPayload | null; contentType: string; headers: Record; } diff --git a/x-pack/legacy/plugins/reporting/server/usage/get_reporting_usage.ts b/x-pack/legacy/plugins/reporting/server/usage/get_reporting_usage.ts index bd2d0cb835a7902..d794a9236872ebc 100644 --- a/x-pack/legacy/plugins/reporting/server/usage/get_reporting_usage.ts +++ b/x-pack/legacy/plugins/reporting/server/usage/get_reporting_usage.ts @@ -106,7 +106,7 @@ export async function getReportingUsage( exportTypesRegistry: ExportTypesRegistry ) { const config = server.config(); - const reportingIndex = config.get('xpack.reporting.index'); + const reportingIndex = config.get('index'); const params = { index: `${reportingIndex}-*`, @@ -142,10 +142,6 @@ export async function getReportingUsage( return callCluster('search', params) .then((response: AggregationResults) => handleResponse(server, response)) .then((usage: RangeStatSets) => { - // Allow this to explicitly throw an exception if/when this config is deprecated, - // because we shouldn't collect browserType in that case! - const browserType = config.get('xpack.reporting.capture.browser.type'); - const xpackInfo = server.plugins.xpack_main.info; const exportTypesHandler = getExportTypesHandler(exportTypesRegistry); const availability = exportTypesHandler.getAvailability(xpackInfo) as FeatureAvailabilityMap; @@ -154,7 +150,6 @@ export async function getReportingUsage( return { available: true, - browser_type: browserType, enabled: true, lastDay: decorateRangeStats(lastDay, availability), last7Days: decorateRangeStats(last7Days, availability), diff --git a/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.js b/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.js index f761f0d2d270b2c..cd1aebb6877e576 100644 --- a/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.js +++ b/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.js @@ -46,9 +46,9 @@ function getServerMock(customization) { log: () => {}, config: () => ({ get: key => { - if (key === 'xpack.reporting.enabled') { + if (key === 'enabled') { return true; - } else if (key === 'xpack.reporting.index') { + } else if (key === 'index') { return '.reporting-index'; } }, diff --git a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts index 226355f5edc6159..ef8ed3fe12b5eea 100644 --- a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts +++ b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts @@ -35,7 +35,7 @@ export const createMockServer = ({ settings = {} }: any): ServerFacade => { 'server.basePath': '/sbp', 'server.host': 'localhost', 'server.port': 5601, - 'xpack.reporting.kibanaServer': {}, + 'xpack.reporting.kibanaServer': {}, // likely need rewrite }; mockServer.config().get.mockImplementation((key: any) => { return key in settings ? settings[key] : defaultSettings[key]; diff --git a/x-pack/legacy/plugins/reporting/types.d.ts b/x-pack/legacy/plugins/reporting/types.d.ts index 6d769c0d7b717f1..5b2b522d5abc09a 100644 --- a/x-pack/legacy/plugins/reporting/types.d.ts +++ b/x-pack/legacy/plugins/reporting/types.d.ts @@ -147,7 +147,7 @@ export interface QueueConfig { } export interface ScrollConfig { - duration: string; + duration: number; size: number; } diff --git a/x-pack/plugins/reporting/config.ts b/x-pack/plugins/reporting/config.ts deleted file mode 100644 index f1d6b1a8f248fb0..000000000000000 --- a/x-pack/plugins/reporting/config.ts +++ /dev/null @@ -1,10 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -export const reportingPollConfig = { - jobCompletionNotifier: { interval: 10000, intervalErrorMultiplier: 5 }, - jobsRefresh: { interval: 5000, intervalErrorMultiplier: 5 }, -}; diff --git a/x-pack/plugins/reporting/kibana.json b/x-pack/plugins/reporting/kibana.json index 50f552b0d9fb0d2..66dddc7807ad063 100644 --- a/x-pack/plugins/reporting/kibana.json +++ b/x-pack/plugins/reporting/kibana.json @@ -1,8 +1,10 @@ { + "configPath": [ "xpack", "reporting" ], "id": "reporting", - "version": "8.0.0", "kibanaVersion": "kibana", + "optionalPlugins": [ "usageCollection" ], "requiredPlugins": [], - "server": false, - "ui": true + "server": true, + "ui": true, + "version": "8.0.0" } diff --git a/x-pack/plugins/reporting/server/config/index.ts b/x-pack/plugins/reporting/server/config/index.ts new file mode 100644 index 000000000000000..9e79a1a917ea4af --- /dev/null +++ b/x-pack/plugins/reporting/server/config/index.ts @@ -0,0 +1,36 @@ +/* + * 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 crypto from 'crypto'; +import { map } from 'rxjs/operators'; +import { TypeOf } from '@kbn/config-schema'; +import { PluginInitializerContext } from '../../../../../src/core/server'; +import { ConfigSchema, ConfigType } from './schema'; + +export function createConfig$(context: PluginInitializerContext) { + return context.config.create>().pipe( + map(config => { + const logger = context.logger.get('config'); + + let encryptionKey = config.encryptionKey; + if (encryptionKey === undefined) { + logger.warn( + 'Generating a random key for xpack.reporting.encryptionKey. To prevent sessions from being invalidated on ' + + 'restart, please set xpack.reporting.encryptionKey in kibana.yml' + ); + + encryptionKey = crypto.randomBytes(16).toString('hex'); + } + + return { + ...config, + encryptionKey, + }; + }) + ); +} + +export { ConfigSchema, ConfigType }; diff --git a/x-pack/plugins/reporting/server/config/schema.ts b/x-pack/plugins/reporting/server/config/schema.ts new file mode 100644 index 000000000000000..350983bff792b61 --- /dev/null +++ b/x-pack/plugins/reporting/server/config/schema.ts @@ -0,0 +1,149 @@ +/* + * 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 moment from 'moment'; +import { schema, TypeOf } from '@kbn/config-schema'; + +// xpack.reporting.kibanaServer +const KibanaServerSchema = schema.object({ + protocol: schema.string({ + defaultValue: schema.contextRef('server.port'), + validate(value) { + if (!/^https?$/.test(value)) { + return 'must be "http" or "https"'; + } + }, + }), + hostname: schema.string({ + defaultValue: schema.contextRef('server.host'), + validate(value) { + if (value === '0') { + return 'must not be "0" for the headless browser to correctly resolve the host'; + } + }, + hostname: true, + }), + port: schema.number(), +}); +// xpack.reporting.queue +const QueueSchema = schema.object({ + indexInterval: schema.string({ defaultValue: 'week' }), + pollEnabled: schema.boolean({ defaultValue: true }), + pollInterval: schema.number({ defaultValue: 3000 }), + pollIntervalErrorMultiplier: schema.number({ defaultValue: 10 }), + timeout: schema.number({ defaultValue: moment.duration(2, 'm').asMilliseconds() }), // TODO use schema.duration (breaking change) +}); +// xpack.reporting.capture.networkPolicy.rules +const RulesSchema = schema.object({ + allow: schema.boolean(), + protocol: schema.string(), +}); +// xpack.reporting.capture +const CaptureSchema = schema.object({ + networkPolicy: schema.object({ + enabled: schema.boolean({ defaultValue: true }), + rules: schema.arrayOf(RulesSchema, { + defaultValue: [ + { allow: true, protocol: 'http:' }, + { allow: true, protocol: 'https:' }, + { allow: true, protocol: 'ws:' }, + { allow: true, protocol: 'wss:' }, + { allow: true, protocol: 'data:' }, + { allow: false }, // Default action is to deny! + ], + }), + }), + zoom: schema.number({ defaultValue: 2 }), + viewport: schema.object({ + width: schema.number({ defaultValue: 1950 }), + height: schema.number({ defaultValue: 1200 }), + }), + loadDelay: schema.number({ + defaultValue: moment.duration(3, 's').asMilliseconds(), + }), // TODO schema.duration + browser: schema.object({ + autoDownload: schema.boolean({ + defaultValue: true, // TODO not configurable for $dist + }), + chromium: schema.object({ + inspect: schema.boolean({ + defaultValue: false, // TODO not configurable for $dist + }), + disableSandbox: schema.boolean({ + defaultValue: false, + }), + proxy: schema.object({ + enabled: schema.boolean({ defaultValue: false }), + server: schema.conditional( + schema.siblingRef('enabled'), + true, + schema.uri({ + scheme: ['http', 'https'], + }), + schema.never() + ), + bypass: schema.conditional( + schema.siblingRef('enabled'), + true, + schema.arrayOf(schema.string({ hostname: true })), + schema.never() + ), + }), + maxScreenshotDimension: schema.number({ + defaultValue: 1950, + }), + }), + }), + maxAttempts: schema.number({ defaultValue: 1 }), // defaultValue in 8.0 +}); + +const CsvSchema = schema.object({ + checkForFormulas: schema.boolean({ defaultValue: true }), + enablePanelActionDownload: schema.boolean({ defaultValue: true }), + maxSizeBytes: schema.byteSize({ + defaultValue: 1024 * 1024 * 10, // 10MB = bytes in a kB * kB in a mB * 10 + }), + scroll: schema.object({ + duration: schema.number({ + defaultValue: moment.duration(30, 's').asMilliseconds(), + }), // TODO schema.duration + size: schema.number({ defaultValue: 500 }), + }), +}); + +const EncryptionKeySchema = schema.string({ minLength: 32 }); + +const RolesSchema = schema.object({}); + +const IndexSchema = schema.string({ defaultValue: '.reporting' }); + +const PollSchema = schema.object({ + jobCompletionNotifier: schema.object({ + interval: schema.number({ + defaultValue: moment.duration(10, 's').asMilliseconds(), + }), // TODO schema.duration + intervalErrorMultiplier: schema.number({ defaultValue: 5 }), + }), + jobsRefresh: schema.object({ + interval: schema.number({ + defaultValue: moment.duration(5, 's').asMilliseconds(), + }), // TODO schema.duration + intervalErrorMultiplier: schema.number({ defaultValue: 5 }), + }), +}); + +export const ConfigSchema = schema.object({ + kibanaServer: KibanaServerSchema, + queue: QueueSchema, + capture: CaptureSchema, + csv: CsvSchema, + encryptionKey: EncryptionKeySchema, + roles: RolesSchema, + index: IndexSchema, + poll: PollSchema, +}); + +export type ConfigType = TypeOf; diff --git a/x-pack/plugins/reporting/server/index.ts b/x-pack/plugins/reporting/server/index.ts new file mode 100644 index 000000000000000..1cb935826232eea --- /dev/null +++ b/x-pack/plugins/reporting/server/index.ts @@ -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; + * you may not use this file except in compliance with the Elastic License. + */ + +export { PluginsSetup } from './plugin'; + +import { PluginInitializerContext } from 'src/core/server'; +import { ConfigSchema } from './config'; +import { ReportingPlugin } from './plugin'; + +export const config = { schema: ConfigSchema }; +export const plugin = (initializerContext: PluginInitializerContext) => + new ReportingPlugin(initializerContext); diff --git a/x-pack/plugins/reporting/server/plugin.ts b/x-pack/plugins/reporting/server/plugin.ts new file mode 100644 index 000000000000000..f8b465798d1f530 --- /dev/null +++ b/x-pack/plugins/reporting/server/plugin.ts @@ -0,0 +1,38 @@ +/* + * 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 { Observable } from 'rxjs'; +import { first } from 'rxjs/operators'; +import { CoreSetup, Logger, Plugin, PluginInitializerContext } from '../../../../src/core/server'; +import { ConfigType, createConfig$ } from './config'; + +export interface PluginsSetup { + /** @deprecated */ + __legacy: { + config$: Observable; + }; +} + +export class ReportingPlugin implements Plugin { + private readonly log: Logger; + + constructor(private readonly initializerContext: PluginInitializerContext) { + this.log = this.initializerContext.logger.get(); + } + + public async setup(core: CoreSetup): Promise { + return { + __legacy: { + config$: createConfig$(this.initializerContext).pipe(first()), + }, + }; + } + + public start() { + this.log.info('starting reporting services...'); + } + public stop() {} +}