diff --git a/x-pack/legacy/plugins/reporting/__snapshots__/index.test.js.snap b/x-pack/legacy/plugins/reporting/__snapshots__/index.test.js.snap deleted file mode 100644 index 469f5e6e7b3c6e8..000000000000000 --- a/x-pack/legacy/plugins/reporting/__snapshots__/index.test.js.snap +++ /dev/null @@ -1,363 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`config schema with context {"dev":false,"dist":false} produces correct config 1`] = ` -Object { - "capture": Object { - "browser": Object { - "autoDownload": true, - "chromium": Object { - "disableSandbox": "", - "maxScreenshotDimension": 1950, - "proxy": Object { - "enabled": false, - }, - }, - "type": "chromium", - }, - "concurrency": 4, - "loadDelay": 3000, - "maxAttempts": 1, - "networkPolicy": Object { - "enabled": true, - "rules": Array [ - Object { - "allow": true, - "protocol": "http:", - }, - Object { - "allow": true, - "protocol": "https:", - }, - Object { - "allow": true, - "protocol": "ws:", - }, - Object { - "allow": true, - "protocol": "wss:", - }, - Object { - "allow": true, - "protocol": "data:", - }, - Object { - "allow": false, - }, - ], - }, - "settleTime": 1000, - "timeout": 20000, - "viewport": Object { - "height": 1200, - "width": 1950, - }, - "zoom": 2, - }, - "csv": Object { - "checkForFormulas": true, - "enablePanelActionDownload": true, - "maxSizeBytes": 10485760, - "scroll": Object { - "duration": "30s", - "size": 500, - }, - }, - "enabled": true, - "encryptionKey": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "index": ".reporting", - "kibanaServer": Object {}, - "poll": Object { - "jobCompletionNotifier": Object { - "interval": 10000, - "intervalErrorMultiplier": 5, - }, - "jobsRefresh": Object { - "interval": 5000, - "intervalErrorMultiplier": 5, - }, - }, - "queue": Object { - "indexInterval": "week", - "pollEnabled": true, - "pollInterval": 3000, - "pollIntervalErrorMultiplier": 10, - "timeout": 120000, - }, - "roles": Object { - "allow": Array [ - "reporting_user", - ], - }, -} -`; - -exports[`config schema with context {"dev":false,"dist":true} produces correct config 1`] = ` -Object { - "capture": Object { - "browser": Object { - "autoDownload": false, - "chromium": Object { - "disableSandbox": "", - "maxScreenshotDimension": 1950, - "proxy": Object { - "enabled": false, - }, - }, - "type": "chromium", - }, - "concurrency": 4, - "loadDelay": 3000, - "maxAttempts": 3, - "networkPolicy": Object { - "enabled": true, - "rules": Array [ - Object { - "allow": true, - "protocol": "http:", - }, - Object { - "allow": true, - "protocol": "https:", - }, - Object { - "allow": true, - "protocol": "ws:", - }, - Object { - "allow": true, - "protocol": "wss:", - }, - Object { - "allow": true, - "protocol": "data:", - }, - Object { - "allow": false, - }, - ], - }, - "settleTime": 1000, - "timeout": 20000, - "viewport": Object { - "height": 1200, - "width": 1950, - }, - "zoom": 2, - }, - "csv": Object { - "checkForFormulas": true, - "enablePanelActionDownload": true, - "maxSizeBytes": 10485760, - "scroll": Object { - "duration": "30s", - "size": 500, - }, - }, - "enabled": true, - "index": ".reporting", - "kibanaServer": Object {}, - "poll": Object { - "jobCompletionNotifier": Object { - "interval": 10000, - "intervalErrorMultiplier": 5, - }, - "jobsRefresh": Object { - "interval": 5000, - "intervalErrorMultiplier": 5, - }, - }, - "queue": Object { - "indexInterval": "week", - "pollEnabled": true, - "pollInterval": 3000, - "pollIntervalErrorMultiplier": 10, - "timeout": 120000, - }, - "roles": Object { - "allow": Array [ - "reporting_user", - ], - }, -} -`; - -exports[`config schema with context {"dev":true,"dist":false} produces correct config 1`] = ` -Object { - "capture": Object { - "browser": Object { - "autoDownload": true, - "chromium": Object { - "disableSandbox": "", - "maxScreenshotDimension": 1950, - "proxy": Object { - "enabled": false, - }, - }, - "type": "chromium", - }, - "concurrency": 4, - "loadDelay": 3000, - "maxAttempts": 1, - "networkPolicy": Object { - "enabled": true, - "rules": Array [ - Object { - "allow": true, - "protocol": "http:", - }, - Object { - "allow": true, - "protocol": "https:", - }, - Object { - "allow": true, - "protocol": "ws:", - }, - Object { - "allow": true, - "protocol": "wss:", - }, - Object { - "allow": true, - "protocol": "data:", - }, - Object { - "allow": false, - }, - ], - }, - "settleTime": 1000, - "timeout": 20000, - "viewport": Object { - "height": 1200, - "width": 1950, - }, - "zoom": 2, - }, - "csv": Object { - "checkForFormulas": true, - "enablePanelActionDownload": true, - "maxSizeBytes": 10485760, - "scroll": Object { - "duration": "30s", - "size": 500, - }, - }, - "enabled": true, - "encryptionKey": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "index": ".reporting", - "kibanaServer": Object {}, - "poll": Object { - "jobCompletionNotifier": Object { - "interval": 10000, - "intervalErrorMultiplier": 5, - }, - "jobsRefresh": Object { - "interval": 5000, - "intervalErrorMultiplier": 5, - }, - }, - "queue": Object { - "indexInterval": "week", - "pollEnabled": true, - "pollInterval": 3000, - "pollIntervalErrorMultiplier": 10, - "timeout": 120000, - }, - "roles": Object { - "allow": Array [ - "reporting_user", - ], - }, -} -`; - -exports[`config schema with context {"dev":true,"dist":true} produces correct config 1`] = ` -Object { - "capture": Object { - "browser": Object { - "autoDownload": false, - "chromium": Object { - "disableSandbox": "", - "maxScreenshotDimension": 1950, - "proxy": Object { - "enabled": false, - }, - }, - "type": "chromium", - }, - "concurrency": 4, - "loadDelay": 3000, - "maxAttempts": 3, - "networkPolicy": Object { - "enabled": true, - "rules": Array [ - Object { - "allow": true, - "protocol": "http:", - }, - Object { - "allow": true, - "protocol": "https:", - }, - Object { - "allow": true, - "protocol": "ws:", - }, - Object { - "allow": true, - "protocol": "wss:", - }, - Object { - "allow": true, - "protocol": "data:", - }, - Object { - "allow": false, - }, - ], - }, - "settleTime": 1000, - "timeout": 20000, - "viewport": Object { - "height": 1200, - "width": 1950, - }, - "zoom": 2, - }, - "csv": Object { - "checkForFormulas": true, - "enablePanelActionDownload": true, - "maxSizeBytes": 10485760, - "scroll": Object { - "duration": "30s", - "size": 500, - }, - }, - "enabled": true, - "index": ".reporting", - "kibanaServer": Object {}, - "poll": Object { - "jobCompletionNotifier": Object { - "interval": 10000, - "intervalErrorMultiplier": 5, - }, - "jobsRefresh": Object { - "interval": 5000, - "intervalErrorMultiplier": 5, - }, - }, - "queue": Object { - "indexInterval": "week", - "pollEnabled": true, - "pollInterval": 3000, - "pollIntervalErrorMultiplier": 10, - "timeout": 120000, - }, - "roles": Object { - "allow": Array [ - "reporting_user", - ], - }, -} -`; 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..cf479a68caa534c 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') ); }); @@ -50,12 +50,12 @@ describe('conditions', () => { server: mockServer, }); - expect(conditionalHeaders.conditions.hostname).toEqual(mockServer.config().get('server.host')); + expect(conditionalHeaders.conditions.hostname).toEqual(mockServer.config.get('server.host')); }); test(`uses port from reporting config if set`, async () => { const settings = { - 'xpack.reporting.kibanaServer.port': 443, + 'kibanaServer.port': 443, }; mockServer = createMockServer({ settings }); @@ -71,9 +71,7 @@ describe('conditions', () => { server: mockServer, }); - expect(conditionalHeaders.conditions.port).toEqual( - mockServer.config().get('xpack.reporting.kibanaServer.port') - ); + expect(conditionalHeaders.conditions.port).toEqual(mockServer.config.get('kibanaServer.port')); }); test(`uses port from server if reporting config not set`, async () => { @@ -88,7 +86,7 @@ describe('conditions', () => { server: mockServer, }); - expect(conditionalHeaders.conditions.port).toEqual(mockServer.config().get('server.port')); + expect(conditionalHeaders.conditions.port).toEqual(mockServer.config.get('server.port')); }); test(`uses basePath from server config`, async () => { @@ -104,13 +102,13 @@ describe('conditions', () => { }); expect(conditionalHeaders.conditions.basePath).toEqual( - mockServer.config().get('server.basePath') + mockServer.config.get('server.basePath') ); }); test(`uses protocol from reporting config if set`, async () => { const settings = { - 'xpack.reporting.kibanaServer.protocol': 'https', + 'kibanaServer.protocol': 'https', }; mockServer = createMockServer({ settings }); @@ -127,7 +125,7 @@ describe('conditions', () => { }); expect(conditionalHeaders.conditions.protocol).toEqual( - mockServer.config().get('xpack.reporting.kibanaServer.protocol') + mockServer.config.get('kibanaServer.protocol') ); }); @@ -143,7 +141,9 @@ describe('conditions', () => { server: mockServer, }); - expect(conditionalHeaders.conditions.protocol).toEqual(mockServer.info.protocol); + expect(conditionalHeaders.conditions.protocol).toEqual( + mockServer.kbnConfig.get('server.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..b1d08a1b50c9d45 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 @@ -14,13 +14,15 @@ export const getConditionalHeaders = ({ job: JobDocPayloadType; filteredHeaders: Record; }) => { - const config = server.config(); + const { config, kbnConfig } = server; + + // FIXME: 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_custom_logo.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.ts index 0059276f6df718f..9bd60d89ec1f416 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.ts @@ -17,8 +17,8 @@ export const getCustomLogo = async ({ job: JobDocPayloadPDF; conditionalHeaders: ConditionalHeaders; }) => { - const serverBasePath: string = server.config().get('server.basePath'); - + const { kbnConfig, savedObjects, uiSettingsServiceFactory } = server; + const serverBasePath: string = kbnConfig.get('server.basePath'); const fakeRequest: any = { headers: conditionalHeaders.headers, // This is used by the spaces SavedObjectClientWrapper to determine the existing space. @@ -37,9 +37,8 @@ export const getCustomLogo = async ({ }, }; - const savedObjects = server.savedObjects; const savedObjectsClient = savedObjects.getScopedSavedObjectsClient(fakeRequest); - const uiSettings = server.uiSettingsServiceFactory({ savedObjectsClient }); + const uiSettings = uiSettingsServiceFactory({ savedObjectsClient }); const logo: string = await uiSettings.get(UI_SETTINGS_CUSTOM_PDF_LOGO); return { conditionalHeaders, logo }; }; 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..73d91bb131d40b5 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 @@ -30,13 +30,14 @@ export function getFullUrls({ server: ServerFacade; job: JobDocPayloadPDF | JobDocPayloadPNG; }) { - const config = server.config(); + const { config, kbnConfig } = server; + // 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..b3396a44418a664 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 @@ -20,9 +20,9 @@ export class PrintLayout extends Layout { public readonly groupCount = 2; private captureConfig: CaptureConfig; - constructor(server: ServerFacade) { + constructor({ config }: ServerFacade) { super(LayoutTypes.PRINT); - this.captureConfig = server.config().get('xpack.reporting.capture'); + this.captureConfig = 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..369bb1e360c219b 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 @@ -6,7 +6,7 @@ import * as Rx from 'rxjs'; import { first, mergeMap, toArray } from 'rxjs/operators'; -import { ServerFacade, CaptureConfig, HeadlessChromiumDriverFactory } from '../../../../types'; +import { ServerFacade, HeadlessChromiumDriverFactory } from '../../../../types'; import { ScreenshotResults, ScreenshotObservableOpts } from './types'; import { injectCustomCss } from './inject_css'; import { openUrl } from './open_url'; @@ -20,12 +20,9 @@ import { scanPage } from './scan_page'; import { skipTelemetry } from './skip_telemetry'; export function screenshotsObservableFactory( - server: ServerFacade, + { config }: ServerFacade, browserDriverFactory: HeadlessChromiumDriverFactory ) { - const config = server.config(); - const captureConfig: CaptureConfig = config.get('xpack.reporting.capture'); - return function screenshotsObservable({ logger, urls, @@ -64,7 +61,7 @@ export function screenshotsObservableFactory( await layout.positionElements(driver, logger); } - await waitForRenderComplete(captureConfig, driver, layout, logger); + await waitForRenderComplete(config.get('capture'), driver, layout, logger); }), mergeMap(() => getTimeRange(driver, layout, logger)), mergeMap( 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 6a6c16705dbced0..218922e04d0eef1 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 @@ -86,11 +86,8 @@ describe('CSV Execute Job', function() { return fieldFormatsRegistry; }, - config: function() { - return { - get: configGetStub, - }; - }, + config: { get: configGetStub }, + kbnConfig: { get: configGetStub }, savedObjects: { getScopedSavedObjectsClient: sinon.stub(), }, @@ -99,18 +96,9 @@ describe('CSV Execute Job', function() { }), log: function() {}, }; - mockServer - .config() - .get.withArgs('xpack.reporting.encryptionKey') - .returns(encryptionKey); - mockServer - .config() - .get.withArgs('xpack.reporting.csv.maxSizeBytes') - .returns(1024 * 1000); // 1mB - mockServer - .config() - .get.withArgs('xpack.reporting.csv.scroll') - .returns({}); + mockServer.config.get.withArgs('encryptionKey').returns(encryptionKey); + mockServer.config.get.withArgs('csv.maxSizeBytes').returns(1024 * 1000); // 1mB + mockServer.config.get.withArgs('csv.scroll').returns({}); }); describe('calls getScopedSavedObjectsClient with request', function() { @@ -129,10 +117,7 @@ describe('CSV Execute Job', function() { it(`containing getBasePath() returning server's basePath if the job doesn't have one`, async function() { const serverBasePath = '/foo-server/basePath/'; - mockServer - .config() - .get.withArgs('server.basePath') - .returns(serverBasePath); + mockServer.config.get.withArgs('server.basePath').returns(serverBasePath); const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); await executeJob( 'job456', @@ -147,10 +132,7 @@ describe('CSV Execute Job', function() { it(`containing getBasePath() returning job's basePath if the job has one`, async function() { const serverBasePath = '/foo-server/basePath/'; - mockServer - .config() - .get.withArgs('server.basePath') - .returns(serverBasePath); + mockServer.config.get.withArgs('server.basePath').returns(serverBasePath); const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); const jobBasePath = 'foo-job/basePath/'; await executeJob( @@ -358,10 +340,7 @@ describe('CSV Execute Job', function() { describe('Cells with formula values', () => { it('returns `csv_contains_formulas` when cells contain formulas', async function() { - mockServer - .config() - .get.withArgs('xpack.reporting.csv.checkForFormulas') - .returns(true); + mockServer.config.get.withArgs('csv.checkForFormulas').returns(true); callWithRequestStub.onFirstCall().returns({ hits: { hits: [{ _source: { one: '=SUM(A1:A2)', two: 'bar' } }], @@ -386,10 +365,7 @@ describe('CSV Execute Job', function() { }); it('returns warnings when headings contain formulas', async function() { - mockServer - .config() - .get.withArgs('xpack.reporting.csv.checkForFormulas') - .returns(true); + mockServer.config.get.withArgs('csv.checkForFormulas').returns(true); callWithRequestStub.onFirstCall().returns({ hits: { hits: [{ _source: { '=SUM(A1:A2)': 'foo', two: 'bar' } }], @@ -414,10 +390,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') - .returns(true); + mockServer.config.get.withArgs('csv.checkForFormulas').returns(true); callWithRequestStub.onFirstCall().returns({ hits: { hits: [{ _source: { one: 'foo', two: 'bar' } }], @@ -442,10 +415,7 @@ describe('CSV Execute Job', function() { }); it('returns no warnings when configured not to', async () => { - mockServer - .config() - .get.withArgs('xpack.reporting.csv.checkForFormulas') - .returns(false); + mockServer.config.get.withArgs('csv.checkForFormulas').returns(false); callWithRequestStub.onFirstCall().returns({ hits: { hits: [{ _source: { one: '=SUM(A1:A2)', two: 'bar' } }], @@ -827,10 +797,7 @@ describe('CSV Execute Job', function() { let maxSizeReached; beforeEach(async function() { - mockServer - .config() - .get.withArgs('xpack.reporting.csv.maxSizeBytes') - .returns(1); + mockServer.config.get.withArgs('csv.maxSizeBytes').returns(1); const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); const jobParams = { @@ -860,10 +827,7 @@ describe('CSV Execute Job', function() { let maxSizeReached; beforeEach(async function() { - mockServer - .config() - .get.withArgs('xpack.reporting.csv.maxSizeBytes') - .returns(9); + mockServer.config.get.withArgs('csv.maxSizeBytes').returns(9); const executeJob = executeJobFactory(mockServer, mockElasticsearch, mockLogger); const jobParams = { @@ -893,10 +857,7 @@ describe('CSV Execute Job', function() { let maxSizeReached; beforeEach(async function() { - mockServer - .config() - .get.withArgs('xpack.reporting.csv.maxSizeBytes') - .returns(9); + mockServer.config.get.withArgs('csv.maxSizeBytes').returns(9); callWithRequestStub.onFirstCall().returns({ hits: { @@ -934,10 +895,7 @@ describe('CSV Execute Job', function() { let maxSizeReached; beforeEach(async function() { - mockServer - .config() - .get.withArgs('xpack.reporting.csv.maxSizeBytes') - .returns(18); + mockServer.config.get.withArgs('csv.maxSizeBytes').returns(18); callWithRequestStub.onFirstCall().returns({ hits: { @@ -974,10 +932,7 @@ describe('CSV Execute Job', function() { describe('scroll settings', function() { it('passes scroll duration to initial search call', async function() { const scrollDuration = 'test'; - mockServer - .config() - .get.withArgs('xpack.reporting.csv.scroll') - .returns({ duration: scrollDuration }); + mockServer.config.get.withArgs('csv.scroll').returns({ duration: scrollDuration }); callWithRequestStub.onFirstCall().returns({ hits: { @@ -1003,10 +958,7 @@ describe('CSV Execute Job', function() { it('passes scroll size to initial search call', async function() { const scrollSize = 100; - mockServer - .config() - .get.withArgs('xpack.reporting.csv.scroll') - .returns({ size: scrollSize }); + mockServer.config.get.withArgs('csv.scroll').returns({ size: scrollSize }); callWithRequestStub.onFirstCall().resolves({ hits: { @@ -1032,10 +984,7 @@ describe('CSV Execute Job', function() { it('passes scroll duration to subsequent scroll call', async function() { const scrollDuration = 'test'; - mockServer - .config() - .get.withArgs('xpack.reporting.csv.scroll') - .returns({ duration: scrollDuration }); + mockServer.config.get.withArgs('csv.scroll').returns({ duration: scrollDuration }); callWithRequestStub.onFirstCall().resolves({ hits: { 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 192274b506cbf07..19d836c710df966 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 @@ -21,11 +21,11 @@ export const executeJobFactory: ExecuteJobFactory; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts b/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts index 842330fa7c93f3f..1984c8166968412 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts @@ -5,7 +5,13 @@ */ import { CancellationToken } from '../../common/cancellation_token'; -import { JobDocPayload, JobParamPostPayload, ConditionalHeaders, RequestFacade } from '../../types'; +import { + JobDocPayload, + JobParamPostPayload, + ConditionalHeaders, + RequestFacade, + ScrollConfig, +} from '../../types'; interface DocValueField { field: string; @@ -106,7 +112,7 @@ export interface GenerateCsvParams { quoteValues: boolean; timezone: string | null; maxSizeBytes: number; - scroll: { duration: string; size: number }; + scroll: ScrollConfig; checkForFormulas?: boolean; }; } diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts index b63fc48faf9177d..d45aed510a3eaff 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts @@ -64,7 +64,7 @@ export async function generateCsvSearch( searchPanel: SearchPanel, jobParams: JobParamsDiscoverCsv ): Promise { - const { savedObjects, uiSettingsServiceFactory } = server; + const { savedObjects, uiSettingsServiceFactory, config } = server; const savedObjectsClient = savedObjects.getScopedSavedObjectsClient( KibanaRequest.from(req.getRawRequest()) ); @@ -157,7 +157,6 @@ export async function generateCsvSearch( const { callWithRequest } = elasticsearch.getCluster('data'); const callCluster = (...params: [string, object]) => callWithRequest(req, ...params); - const config = server.config(); const uiSettings = await getUiSettings(uiConfig); const generateCsvParams: GenerateCsvParams = { @@ -170,8 +169,8 @@ export async function generateCsvSearch( cancellationToken: new CancellationToken(), settings: { ...uiSettings, - maxSizeBytes: config.get('xpack.reporting.csv.maxSizeBytes'), - scroll: config.get('xpack.reporting.csv.scroll'), + maxSizeBytes: config.get('csv.maxSizeBytes'), + scroll: config.get('csv.scroll'), timezone, }, }; diff --git a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js index 24d3bcb976b2609..c43a56568f6fa88 100644 --- a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js +++ b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js @@ -21,25 +21,25 @@ let config; let mockServer; beforeEach(() => { config = { - 'xpack.reporting.encryptionKey': 'testencryptionkey', + encryptionKey: 'testencryptionkey', 'server.basePath': '/sbp', 'server.host': 'localhost', 'server.port': 5601, + 'server.protocol': 'http', }; mockServer = { - expose: () => {}, // NOTE: this is for oncePerServer - config: memoize(() => ({ get: jest.fn() })), - info: { - protocol: 'http', - }, + config: { get: jest.fn() }, + kbnConfig: { get: jest.fn() }, savedObjects: { getScopedSavedObjectsClient: jest.fn(), }, uiSettingsServiceFactory: jest.fn().mockReturnValue({ get: jest.fn() }), - log: jest.fn(), }; - mockServer.config().get.mockImplementation(key => { + mockServer.config.get.mockImplementation(key => { + return config[key]; + }); + mockServer.kbnConfig.get.mockImplementation(key => { return config[key]; }); 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 e500db86a5c688d..5e4308e55788d2f 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,25 +21,25 @@ let config; let mockServer; beforeEach(() => { config = { - 'xpack.reporting.encryptionKey': 'testencryptionkey', + encryptionKey: 'testencryptionkey', 'server.basePath': '/sbp', 'server.host': 'localhost', 'server.port': 5601, + 'server.protocol': 'http', }; mockServer = { - expose: jest.fn(), - log: jest.fn(), - config: memoize(() => ({ get: jest.fn() })), - info: { - protocol: 'http', - }, + config: { get: jest.fn() }, + kbnConfig: { get: jest.fn() }, savedObjects: { getScopedSavedObjectsClient: jest.fn(), }, uiSettingsServiceFactory: jest.fn().mockReturnValue({ get: jest.fn() }), }; - mockServer.config().get.mockImplementation(key => { + mockServer.config.get.mockImplementation(key => { + return config[key]; + }); + mockServer.kbnConfig.get.mockImplementation(key => { return config[key]; }); 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 9f3144c2eb4f78b..af0476af4278a31 100644 --- a/x-pack/legacy/plugins/reporting/index.ts +++ b/x-pack/legacy/plugins/reporting/index.ts @@ -6,24 +6,24 @@ import { i18n } from '@kbn/i18n'; import { Legacy } from 'kibana'; +import { get } from 'lodash'; import { IUiSettingsClient } from 'kibana/server'; import { resolve } from 'path'; +import { take } from 'rxjs/operators'; import { ElasticsearchPlugin } from 'src/legacy/core_plugins/elasticsearch'; +import { PluginsSetup } from '../../../plugins/reporting/server'; import { PluginStart as DataPluginStart } from '../../../../src/plugins/data/server'; import { PluginSetupContract as SecurityPluginSetup } from '../../../plugins/security/server'; import { PLUGIN_ID, UI_SETTINGS_CUSTOM_PDF_LOGO } from './common/constants'; -import { config as reportingConfig } from './config'; import { LegacySetup, ReportingPlugin, reportingPluginFactory, ReportingSetupDeps, } from './server/plugin'; -import { ReportingConfigOptions, ReportingPluginSpecOptions } from './types.d'; +import { ReportingPluginSpecOptions } from './types.d'; -const kbToBase64Length = (kb: number) => { - return Math.floor((kb * 1024 * 8) / 6); -}; +const kbToBase64Length = (kb: number) => Math.floor((kb * 1024 * 8) / 6); interface ReportingDeps { data: DataPluginStart; @@ -32,10 +32,8 @@ interface ReportingDeps { 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: [ @@ -45,13 +43,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', { @@ -88,8 +79,32 @@ export const reporting = (kibana: any) => { return fieldFormats.fieldFormatServiceFactory(uiSettings); }; + const { + __legacy: { config$ }, + } = server.newPlatform.setup.plugins.reporting as PluginsSetup; + const currentConfig = await config$.pipe(take(1)).toPromise(); + const config = server.config(); // FIXME for getting legacy configs + 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: { xpack_main: server.plugins.xpack_main }, @@ -102,14 +117,5 @@ export const reporting = (kibana: any) => { const plugin: ReportingPlugin = reportingPluginFactory(initializerContext, __LEGACY, this); await plugin.setup(coreSetup, pluginsSetup); }, - - deprecations({ unused }: any) { - return [ - unused('capture.concurrency'), - unused('capture.timeout'), - unused('capture.settleTime'), - unused('kibanaApp'), - ]; - }, } as ReportingPluginSpecOptions); }; diff --git a/x-pack/legacy/plugins/reporting/log_configuration.ts b/x-pack/legacy/plugins/reporting/log_configuration.ts index b07475df6304ff3..00aa6aae5cf13d8 100644 --- a/x-pack/legacy/plugins/reporting/log_configuration.ts +++ b/x-pack/legacy/plugins/reporting/log_configuration.ts @@ -10,19 +10,14 @@ import { ServerFacade, Logger } from './types'; 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'); +export async function logConfiguration({ config }: ServerFacade, logger: Logger) { + 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..ebe7af5e7f76d07 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 @@ -12,18 +12,16 @@ import { chromium } from './index'; import { HeadlessChromiumDriverFactory } from './chromium/driver_factory'; export async function createBrowserDriverFactory( - server: ServerFacade, + { config, kbnConfig }: ServerFacade, logger: Logger ): Promise { - const config = server.config(); - - 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 e01ed305c267709..e45d8ba1615af96 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts @@ -28,8 +28,9 @@ 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 { config } = server; + const queueConfig: QueueConfig = config.get('queue'); + const index = config.get('index'); const queueOptions = { interval: queueConfig.indexInterval, @@ -49,6 +50,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 41b9c6867c2592b..371920343181a4f 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 @@ -15,7 +15,7 @@ import { ClientMock } from './esqueue/__tests__/fixtures/legacy_elasticsearch'; import { ExportTypesRegistry } from './export_types_registry'; const configGetStub = sinon.stub(); -configGetStub.withArgs('xpack.reporting.queue').returns({ +configGetStub.withArgs('queue').returns({ pollInterval: 3300, pollIntervalErrorMultiplier: 10, }); @@ -26,7 +26,8 @@ const executeJobFactoryStub = sinon.stub(); const getMockServer = (): ServerFacade => { return ({ - config: () => ({ get: configGetStub }), + config: { get: configGetStub }, + kbnConfig: { get: configGetStub }, } as unknown) as ServerFacade; }; const getMockLogger = jest.fn(); 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 d1f9d9db37022a8..1fb20eb3d5f7576 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts @@ -35,10 +35,11 @@ export function createWorkerFactory( { exportTypesRegistry, browserDriverFactory }: CreateWorkerFactoryOpts ) { 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 { config, kbnConfig } = server; + 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..ee706b29d2297b5 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/crypto.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/crypto.ts @@ -8,8 +8,8 @@ import nodeCrypto from '@elastic/node-crypto'; import { oncePerServer } from './once_per_server'; import { ServerFacade } from '../../types'; -function cryptoFn(server: ServerFacade) { - const encryptionKey = server.config().get('xpack.reporting.encryptionKey'); +function cryptoFn({ config }: ServerFacade) { + const encryptionKey = 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 c75414d18e09819..b201535c5292409 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts @@ -41,11 +41,11 @@ export function enqueueJobFactory( { exportTypesRegistry, esqueue }: EnqueueJobFactoryOpts ): EnqueueJobFn { const logger = parentLogger.clone(['queue-job']); - const config = server.config(); - const captureConfig: CaptureConfig = config.get('xpack.reporting.capture'); + const { config } = server; + 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 0290eeb97368e1d..6b63fb7e6459da4 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts @@ -38,10 +38,10 @@ interface CountAggResult { } export function jobsQueryFactory( - server: ServerFacade, + { config }: ServerFacade, elasticsearch: ReportingSetupDeps['elasticsearch'] ) { - const index = server.config().get('xpack.reporting.index'); + const index = config.get('index'); const { callWithInternalUser } = elasticsearch.getCluster('admin'); function getUsername(user: any) { 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 ab758835c73bdbb..c69f22bc35c942c 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts @@ -9,9 +9,7 @@ import { ServerFacade, Logger } from '../../../types'; import { ReportingSetupDeps } from '../../plugin'; 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, @@ -22,9 +20,7 @@ export async function runValidations( try { await Promise.all([ validateBrowser(server, browserFactory, logger), - validateEncryptionKey(server, logger), validateMaxContentLength(server, elasticsearch, 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 3c50d95d9a3ba06..0b0f5d38eb0bc15 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 @@ -8,17 +8,15 @@ import { defaults, get } from 'lodash'; import { Logger, ServerFacade } from '../../../types'; import { ReportingSetupDeps } from '../../plugin'; -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, + { config }: ServerFacade, elasticsearch: ReportingSetupDeps['elasticsearch'], logger: Logger ) { - const config = server.config(); const { callWithInternalUser } = elasticsearch.getCluster('data'); - const elasticClusterSettingsResponse = await callWithInternalUser('cluster.getSettings', { includeDefaults: true, }); 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 c9953b4749d01c3..76935133fe9d475 100644 --- a/x-pack/legacy/plugins/reporting/server/plugin.ts +++ b/x-pack/legacy/plugins/reporting/server/plugin.ts @@ -36,8 +36,16 @@ export interface ReportingSetupDeps { } export type ReportingStartDeps = object; +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: { xpack_main: XPackMainPlugin & { status?: any } }; route: Legacy.Server['route']; diff --git a/x-pack/legacy/plugins/reporting/server/routes/generation.ts b/x-pack/legacy/plugins/reporting/server/routes/generation.ts index 02a9541484bc635..b061aeccb299a18 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generation.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generation.ts @@ -31,9 +31,9 @@ export function registerJobGenerationRoutes( browserDriverFactory: HeadlessChromiumDriverFactory, logger: Logger ) { - const config = server.config(); - const DOWNLOAD_BASE_URL = config.get('server.basePath') + `${API_BASE_URL}/jobs/download`; + const { config, kbnConfig } = server; const { elasticsearch } = plugins; + const DOWNLOAD_BASE_URL = kbnConfig.get('server.basePath') + `${API_BASE_URL}/jobs/download`; const esqueue = createQueueFactory(server, elasticsearch, logger, { exportTypesRegistry, browserDriverFactory, @@ -85,7 +85,7 @@ export function registerJobGenerationRoutes( registerGenerateFromJobParams(server, plugins, 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, plugins, handler, handleError, logger); registerGenerateCsvFromSavedObjectImmediate(server, plugins, logger); } diff --git a/x-pack/legacy/plugins/reporting/server/routes/jobs.test.js b/x-pack/legacy/plugins/reporting/server/routes/jobs.test.js index a2c62529de75a03..4e1ce56ca6d6007 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/jobs.test.js +++ b/x-pack/legacy/plugins/reporting/server/routes/jobs.test.js @@ -30,7 +30,7 @@ const mockLogger = { beforeEach(() => { mockServer = new Hapi.Server({ debug: false, port: 8080, routes: { log: { collect: true } } }); - mockServer.config = memoize(() => ({ get: jest.fn() })); + mockServer.config = { get: jest.fn() }; exportTypesRegistry = new ExportTypesRegistry(); exportTypesRegistry.register({ id: 'unencoded', @@ -268,6 +268,7 @@ describe(`when job is completed`, () => { ); expect(errorLogs).toHaveLength(1); expect(errorLogs[0].error).toBeInstanceOf(Error); + console.log(errorLogs[0].error.stack); expect(errorLogs[0].error.message).toMatch(/Unsupported content-type of application\/html/); }); }); 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 3460d22592e3db6..cafc294da81d1b9 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 @@ -17,12 +17,10 @@ describe('authorized_user_pre_routing', function() { const mockServer = { expose() {}, - config() { - return { - get(key) { - return mockConfig[key]; - }, - }; + config: { + get(key) { + return mockConfig[key]; + }, }, log: function() {}, plugins: { @@ -146,7 +144,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 mockPlugins = getMockPlugins({ security: { authc: { getCurrentUser: () => ({ roles: ['something_else'] }) } }, @@ -166,7 +164,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 mockPlugins = getMockPlugins({ security: { @@ -187,7 +185,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 mockPlugins = getMockPlugins({ security: { authc: { getCurrentUser: () => ({ roles: ['superuser', 'something_else'] }) } }, 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 874027251570c35..886224e0b4dd49a 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 @@ -22,12 +22,15 @@ export const authorizedUserPreRoutingFactory = function authorizedUserPreRouting plugins: ReportingSetupDeps, logger: Logger ) { + const { + config, + plugins: { + xpack_main: { info: xpackInfo }, + }, + } = server; const getUser = getUserFactory(server, plugins.security, logger); - const config = server.config(); return async function authorizedUserPreRouting(request: Legacy.Request) { - const xpackInfo = server.plugins.xpack_main.info; - if (!xpackInfo || !xpackInfo.isAvailable()) { logger.warn('Unable to authorize user before xpack info is available.', [ 'authorizedUserPreRouting', @@ -46,10 +49,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 fb3944ea33552f1..0d77b58055922f0 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; contentType: string; headers: Record; } @@ -52,23 +58,24 @@ export function getDocumentPayloadFactory( server: ServerFacade, exportTypesRegistry: ExportTypesRegistry ) { - function encodeContent(content: string | null, exportType: ExportTypeType) { + function encodeContent(content: string | null, exportType: ExportTypeType): Buffer | string { switch (exportType.jobContentEncoding) { case 'base64': - return content ? Buffer.from(content, 'base64') : content; // Buffer.from rejects null + return content ? Buffer.from(content, 'base64') : ''; // convert null to empty string default: - return content; + return content ? content : ''; // convert null to empty string } } - function getCompleted(output: JobDocOutput, jobType: string, title: string) { + function getCompleted(output: JobDocOutput, jobType: string, title: string): Payload { const exportType = exportTypesRegistry.get((item: ExportTypeType) => item.jobType === jobType); const filename = getTitle(exportType, title); const headers = getReportingHeaders(output, exportType); + const content = encodeContent(output.content, exportType); return { statusCode: 200, - content: encodeContent(output.content, exportType), + content, contentType: output.content_type, headers: { ...headers, @@ -77,7 +84,7 @@ export function getDocumentPayloadFactory( }; } - function getFailure(output: JobDocOutput) { + function getFailure(output: JobDocOutput): Payload { return { statusCode: 500, content: { 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..2f0b3344a6499b9 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 @@ -105,9 +105,13 @@ export async function getReportingUsage( callCluster: ESCallCluster, exportTypesRegistry: ExportTypesRegistry ) { - const config = server.config(); - const reportingIndex = config.get('xpack.reporting.index'); - + const { + config, + plugins: { + xpack_main: { info: xpackMainInfo }, + }, + } = server; + const reportingIndex = config.get('index'); const params = { index: `${reportingIndex}-*`, filterPath: 'aggregations.*.buckets', @@ -142,19 +146,15 @@ 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; + const availability = exportTypesHandler.getAvailability( + xpackMainInfo + ) as FeatureAvailabilityMap; const { lastDay, last7Days, ...all } = usage; 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..a34c50730039ef4 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 @@ -26,9 +26,6 @@ function getServerMock(customization) { const getLicenseCheckResults = sinon.stub().returns({}); const defaultServerMock = { plugins: { - security: { - isAuthenticated: sinon.stub().returns(true), - }, xpack_main: { info: { isAvailable: sinon.stub().returns(true), @@ -43,16 +40,15 @@ function getServerMock(customization) { }, }, }, - log: () => {}, - config: () => ({ + 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'; } }, - }), + }, }; return Object.assign(defaultServerMock, customization); } @@ -329,7 +325,6 @@ Object { }, "_all": 54, "available": true, - "browser_type": undefined, "csv": Object { "available": true, "total": 27, 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..e5fc8f1c844296a 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 @@ -3,27 +3,13 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { memoize } from 'lodash'; + import { ServerFacade } from '../types'; export const createMockServer = ({ settings = {} }: any): ServerFacade => { const mockServer = { - expose: () => { - ' '; - }, - config: memoize(() => ({ get: jest.fn() })), - info: { - protocol: 'http', - }, - plugins: { - elasticsearch: { - getCluster: memoize(() => { - return { - callWithRequest: jest.fn(), - }; - }), - }, - }, + config: { get: jest.fn() }, + kbnConfig: { get: jest.fn() }, savedObjects: { getScopedSavedObjectsClient: jest.fn(), }, @@ -31,13 +17,17 @@ export const createMockServer = ({ settings = {} }: any): ServerFacade => { }; const defaultSettings: any = { - 'xpack.reporting.encryptionKey': 'testencryptionkey', + encryptionKey: 'testencryptionkey', + kibanaServer: {}, 'server.basePath': '/sbp', 'server.host': 'localhost', + 'server.protocol': 'http', 'server.port': 5601, - 'xpack.reporting.kibanaServer': {}, }; - mockServer.config().get.mockImplementation((key: any) => { + mockServer.config.get.mockImplementation((key: any) => { + return key in settings ? settings[key] : defaultSettings[key]; + }); + mockServer.kbnConfig.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 2854db94cd823aa..83f19bc2d15f19b 100644 --- a/x-pack/legacy/plugins/reporting/types.d.ts +++ b/x-pack/legacy/plugins/reporting/types.d.ts @@ -144,7 +144,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() {} +}