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}`);
+ }
+}