diff --git a/.telemetryrc.json b/.telemetryrc.json index 30643a104c1cd..2f57566159a70 100644 --- a/.telemetryrc.json +++ b/.telemetryrc.json @@ -1,13 +1,4 @@ [ - { - "output": "src/plugins/telemetry/schema/legacy_oss_plugins.json", - "root": "src/legacy/core_plugins/", - "exclude": [ - "src/legacy/core_plugins/testbed", - "src/legacy/core_plugins/elasticsearch", - "src/legacy/core_plugins/tests_bundle" - ] - }, { "output": "src/plugins/telemetry/schema/oss_plugins.json", "root": "src/plugins/", diff --git a/src/plugins/telemetry/schema/legacy_oss_plugins.json b/src/plugins/telemetry/schema/legacy_oss_plugins.json deleted file mode 100644 index e660ccac9dc36..0000000000000 --- a/src/plugins/telemetry/schema/legacy_oss_plugins.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "properties": { - "csp": { - "properties": { - "strict": { - "type": "boolean" - }, - "warnLegacyBrowsers": { - "type": "boolean" - }, - "rulesChangedFromDefault": { - "type": "boolean" - } - } - } - } -} diff --git a/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/constants.ts b/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/constants.ts index 2d0864b1cb75f..7e4176281db41 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/constants.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/constants.ts @@ -128,6 +128,9 @@ export const DATA_DATASETS_INDEX_PATTERNS = [ { pattern: '*suricata*', patternName: 'suricata' }, // { pattern: '*fsf*', patternName: 'fsf' }, // Disabled because it's too vague { pattern: '*wazuh*', patternName: 'wazuh' }, + + // meow attacks + { pattern: '*meow*', patternName: 'meow' }, ] as const; // Get the unique list of index patterns (some are duplicated for documentation purposes) diff --git a/x-pack/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/plugins/lens/public/app_plugin/app.test.tsx index f92343183a700..70136a486e8c1 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.test.tsx @@ -136,6 +136,7 @@ describe('Lens App', () => { originatingApp: string | undefined; onAppLeave: AppMountParameters['onAppLeave']; history: History; + getAppNameFromId?: (appId: string) => string | undefined; }> { return ({ navigation: navigationStartMock, @@ -187,6 +188,7 @@ describe('Lens App', () => { originatingApp: string | undefined; onAppLeave: AppMountParameters['onAppLeave']; history: History; + getAppNameFromId?: (appId: string) => string | undefined; }>; } @@ -298,6 +300,38 @@ describe('Lens App', () => { ]); }); + it('sets originatingApp breadcrumb when the document title changes', async () => { + const defaultArgs = makeDefaultArgs(); + defaultArgs.originatingApp = 'ultraCoolDashboard'; + defaultArgs.getAppNameFromId = () => 'The Coolest Container Ever Made'; + instance = mount(); + + expect(core.chrome.setBreadcrumbs).toHaveBeenCalledWith([ + { text: 'The Coolest Container Ever Made', onClick: expect.anything() }, + { text: 'Visualize', href: '/testbasepath/app/visualize#/', onClick: expect.anything() }, + { text: 'Create' }, + ]); + + (defaultArgs.docStorage.load as jest.Mock).mockResolvedValue({ + id: '1234', + title: 'Daaaaaaadaumching!', + expression: 'valid expression', + state: { + query: 'fake query', + datasourceMetaData: { filterableIndexPatterns: [{ id: '1', title: 'saved' }] }, + }, + }); + await act(async () => { + instance.setProps({ docId: '1234' }); + }); + + expect(defaultArgs.core.chrome.setBreadcrumbs).toHaveBeenCalledWith([ + { text: 'The Coolest Container Ever Made', onClick: expect.anything() }, + { text: 'Visualize', href: '/testbasepath/app/visualize#/', onClick: expect.anything() }, + { text: 'Daaaaaaadaumching!' }, + ]); + }); + describe('persistence', () => { it('does not load a document if there is no document id', () => { const args = makeDefaultArgs(); diff --git a/x-pack/plugins/lens/public/app_plugin/app.tsx b/x-pack/plugins/lens/public/app_plugin/app.tsx index b20fe2f804683..5ca6f27a0c578 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.tsx @@ -11,6 +11,7 @@ import { i18n } from '@kbn/i18n'; import { NavigationPublicPluginStart } from 'src/plugins/navigation/public'; import { AppMountContext, AppMountParameters, NotificationsStart } from 'kibana/public'; import { History } from 'history'; +import { EuiBreadcrumb } from '@elastic/eui'; import { Query, DataPublicPluginStart, @@ -203,6 +204,16 @@ export function App({ // Sync Kibana breadcrumbs any time the saved document's title changes useEffect(() => { core.chrome.setBreadcrumbs([ + ...(originatingApp && getAppNameFromId + ? [ + { + onClick: (e) => { + core.application.navigateToApp(originatingApp); + }, + text: getAppNameFromId(originatingApp), + } as EuiBreadcrumb, + ] + : []), { href: core.http.basePath.prepend(`/app/visualize#/`), onClick: (e) => { @@ -219,7 +230,15 @@ export function App({ : i18n.translate('xpack.lens.breadcrumbsCreate', { defaultMessage: 'Create' }), }, ]); - }, [core.application, core.chrome, core.http.basePath, state.persistedDoc]); + }, [ + core.application, + core.chrome, + core.http.basePath, + state.persistedDoc, + originatingApp, + redirectTo, + getAppNameFromId, + ]); useEffect( () => { diff --git a/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.test.tsx b/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.test.tsx index 552d523fa4a84..b6dd06595ae7f 100644 --- a/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.test.tsx +++ b/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.test.tsx @@ -421,9 +421,58 @@ describe('LoginForm', () => { expect(window.location.href).toBe(currentURL); expect(coreStartMock.notifications.toasts.addError).toHaveBeenCalledWith(failureReason, { title: 'Could not perform login.', + toastMessage: 'Oh no!', }); }); + it('shows error with message in the `body`', async () => { + const currentURL = `https://some-host/login?next=${encodeURIComponent( + '/some-base-path/app/kibana#/home?_g=()' + )}`; + + const coreStartMock = coreMock.createStart({ basePath: '/some-base-path' }); + coreStartMock.http.post.mockRejectedValue({ + body: { message: 'Oh no! But with much more details!' }, + message: 'Oh no!', + }); + + window.location.href = currentURL; + const wrapper = mountWithIntl( + + ); + + expectPageMode(wrapper, PageMode.Selector); + + wrapper.findWhere((node) => node.key() === 'saml1').simulate('click'); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(coreStartMock.http.post).toHaveBeenCalledTimes(1); + expect(coreStartMock.http.post).toHaveBeenCalledWith('/internal/security/login', { + body: JSON.stringify({ providerType: 'saml', providerName: 'saml1', currentURL }), + }); + + expect(window.location.href).toBe(currentURL); + expect(coreStartMock.notifications.toasts.addError).toHaveBeenCalledWith( + new Error('Oh no! But with much more details!'), + { title: 'Could not perform login.', toastMessage: 'Oh no!' } + ); + }); + it('properly switches to login form', async () => { const currentURL = `https://some-host/login?next=${encodeURIComponent( '/some-base-path/app/kibana#/home?_g=()' diff --git a/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx b/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx index 9ea553af75e00..a929b50fa1ffa 100644 --- a/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx +++ b/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx @@ -451,11 +451,15 @@ export class LoginForm extends Component { window.location.href = location; } catch (err) { - this.props.notifications.toasts.addError(err, { - title: i18n.translate('xpack.security.loginPage.loginSelectorErrorMessage', { - defaultMessage: 'Could not perform login.', - }), - }); + this.props.notifications.toasts.addError( + err?.body?.message ? new Error(err?.body?.message) : err, + { + title: i18n.translate('xpack.security.loginPage.loginSelectorErrorMessage', { + defaultMessage: 'Could not perform login.', + }), + toastMessage: err?.message, + } + ); this.setState({ loadingState: { type: LoadingStateType.None } }); } diff --git a/x-pack/plugins/security_solution/scripts/check_circular_deps/run_check_circular_deps_cli.js b/x-pack/plugins/security_solution/scripts/check_circular_deps/run_check_circular_deps_cli.js index 9b4a57f09066d..ac4102184091d 100644 --- a/x-pack/plugins/security_solution/scripts/check_circular_deps/run_check_circular_deps_cli.js +++ b/x-pack/plugins/security_solution/scripts/check_circular_deps/run_check_circular_deps_cli.js @@ -4,17 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resolve } from 'path'; - /* eslint-disable-next-line import/no-extraneous-dependencies */ import madge from 'madge'; /* eslint-disable-next-line import/no-extraneous-dependencies */ import { run, createFailError } from '@kbn/dev-utils'; +import * as os from 'os'; +import * as path from 'path'; run( - async ({ log }) => { + async ({ log, flags }) => { const result = await madge( - [resolve(__dirname, '../../public'), resolve(__dirname, '../../common')], + [path.resolve(__dirname, '../../public'), path.resolve(__dirname, '../../common')], { fileExtensions: ['ts', 'js', 'tsx'], excludeRegExp: [ @@ -34,6 +34,13 @@ run( const circularFound = result.circular(); if (circularFound.length !== 0) { + if (flags.svg) { + await outputSVGs(circularFound); + } else { + console.log( + 'Run this program with the --svg flag to save an SVG showing the dependency graph.' + ); + } throw createFailError( `SIEM circular dependencies of imports has been found:\n - ${circularFound.join('\n - ')}` ); @@ -42,6 +49,34 @@ run( } }, { - description: 'Check the SIEM plugin for circular deps', + description: + 'Check the Security Solution plugin for circular deps. If any are found, this will throw an Error.', + flags: { + help: ' --svg, Output SVGs of circular dependency graphs', + boolean: ['svg'], + default: { + svg: false, + }, + }, } ); + +async function outputSVGs(circularFound) { + let count = 0; + for (const found of circularFound) { + // Calculate the path using the os tmpdir and an increasing 'count' + const expectedImagePath = path.join(os.tmpdir(), `security_solution-circular-dep-${count}.svg`); + console.log(`Attempting to save SVG for circular dependency: ${found}`); + count++; + + // Graph just the files in the found circular dependency. + const specificGraph = await madge(found, { + fileExtensions: ['ts', 'js', 'tsx'], + }); + + // Output an SVG in the tmp directory + const imagePath = await specificGraph.image(expectedImagePath); + + console.log(`Saved SVG: ${imagePath}`); + } +}