From 41b232b1321a8e8bfc54fc057481ce0c4d45d806 Mon Sep 17 00:00:00 2001
From: FrankHassanabad
Date: Wed, 3 Feb 2021 22:22:36 -0700
Subject: [PATCH 1/8] Adds a warning banner whenever the user has not updated
to the latest alerting migration
---
...ts_detection_callouts_platform_engineer.ts | 84 ++++++++++
...louts_platform_engineer_need_admin.spec.ts | 93 ++++++++++++
...alerts_detection_callouts_readonly.spec.ts | 7 +
...ction_callouts_readonly_need_admin.spec.ts | 143 ++++++++++++++++++
...erts_detection_callouts_t1_analyst.spec.ts | 84 ++++++++++
.../components/callouts/callout.test.tsx | 112 ++++++++++++++
.../common/components/callouts/callout.tsx | 13 +-
.../callouts/callout_description.tsx | 25 ---
.../callouts/callout_persistent_switcher.tsx | 23 +++
.../components/callouts/callout_types.ts | 4 +-
.../common/components/callouts/index.ts | 1 +
.../index.test.tsx | 64 ++++++++
.../need_admin_for_update_callout/index.tsx | 35 +++++
.../translations.tsx | 51 +++++++
.../detection_engine/detection_engine.tsx | 2 +
.../detection_engine/rules/details/index.tsx | 2 +
.../pages/detection_engine/rules/index.tsx | 2 +
17 files changed, 713 insertions(+), 32 deletions(-)
create mode 100644 x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer.ts
create mode 100644 x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts
create mode 100644 x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts
create mode 100644 x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_t1_analyst.spec.ts
create mode 100644 x-pack/plugins/security_solution/public/common/components/callouts/callout.test.tsx
delete mode 100644 x-pack/plugins/security_solution/public/common/components/callouts/callout_description.tsx
create mode 100644 x-pack/plugins/security_solution/public/common/components/callouts/callout_persistent_switcher.tsx
create mode 100644 x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx
create mode 100644 x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx
create mode 100644 x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/translations.tsx
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer.ts
new file mode 100644
index 0000000000000..fc1ee8c17a7af
--- /dev/null
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer.ts
@@ -0,0 +1,84 @@
+/*
+ * 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 { ROLES } from '../../../common/test';
+import { DETECTIONS_RULE_MANAGEMENT_URL, DETECTIONS_URL } from '../../urls/navigation';
+import { newRule } from '../../objects/rule';
+import { PAGE_TITLE } from '../../screens/common/page';
+
+import {
+ loginAndWaitForPageWithoutDateRange,
+ waitForPageWithoutDateRange,
+} from '../../tasks/login';
+import { waitForAlertsIndexToBeCreated } from '../../tasks/alerts';
+import { goToRuleDetails } from '../../tasks/alerts_detection_rules';
+import { createCustomRule, deleteCustomRule } from '../../tasks/api_calls/rules';
+import { getCallOut } from '../../tasks/common/callouts';
+import { cleanKibana } from '../../tasks/common';
+
+const loadPageAsPlatformEngineerUser = (url: string) => {
+ waitForPageWithoutDateRange(url, ROLES.platform_engineer);
+ waitForPageTitleToBeShown();
+};
+
+const waitForPageTitleToBeShown = () => {
+ cy.get(PAGE_TITLE).should('be.visible');
+};
+
+describe('Detections > Need Admin Callouts indicating an admin is needed to migrate the alert data set', () => {
+ const NEED_ADMIN_FOR_UPDATE_CALLOUT = 'need-admin-for-update-rules';
+ const ALERTS_CALLOUT = 'read-only-access-to-alerts';
+ const RULES_CALLOUT = 'read-only-access-to-rules';
+
+ before(() => {
+ cleanKibana();
+ loginAndWaitForPageWithoutDateRange(DETECTIONS_URL, ROLES.platform_engineer);
+ waitForAlertsIndexToBeCreated();
+ });
+
+ context('On Detections home page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineerUser(DETECTIONS_URL);
+ });
+
+ it('We show no callouts', () => {
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
+ });
+ });
+
+ context('On Rules Management page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ });
+
+ it('We show no callouts', () => {
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
+ });
+ });
+
+ context('On Rule Details page', () => {
+ beforeEach(() => {
+ createCustomRule(newRule);
+ loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ waitForPageTitleToBeShown();
+ goToRuleDetails();
+ });
+
+ afterEach(() => {
+ deleteCustomRule();
+ });
+
+ it('We show no callouts', () => {
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
+ });
+ });
+});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts
new file mode 100644
index 0000000000000..3645854e67468
--- /dev/null
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts
@@ -0,0 +1,93 @@
+/*
+ * 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 { ROLES } from '../../../common/test';
+import { DETECTIONS_RULE_MANAGEMENT_URL, DETECTIONS_URL } from '../../urls/navigation';
+import { newRule } from '../../objects/rule';
+import { PAGE_TITLE } from '../../screens/common/page';
+
+import {
+ loginAndWaitForPageWithoutDateRange,
+ waitForPageWithoutDateRange,
+} from '../../tasks/login';
+import { waitForAlertsIndexToBeCreated } from '../../tasks/alerts';
+import { goToRuleDetails } from '../../tasks/alerts_detection_rules';
+import { createCustomRule, deleteCustomRule } from '../../tasks/api_calls/rules';
+import { getCallOut, waitForCallOutToBeShown } from '../../tasks/common/callouts';
+import { cleanKibana } from '../../tasks/common';
+
+const loadPageAsPlatformEngineerUser = (url: string) => {
+ waitForPageWithoutDateRange(url, ROLES.platform_engineer);
+ waitForPageTitleToBeShown();
+};
+
+const waitForPageTitleToBeShown = () => {
+ cy.get(PAGE_TITLE).should('be.visible');
+};
+
+describe('Detections > Need Admin Callouts indicating an admin is needed to migrate the alert data set', () => {
+ const NEED_ADMIN_FOR_UPDATE_CALLOUT = 'need-admin-for-update-rules';
+ const ALERTS_CALLOUT = 'read-only-access-to-alerts';
+ const RULES_CALLOUT = 'read-only-access-to-rules';
+
+ before(() => {
+ cleanKibana();
+ loginAndWaitForPageWithoutDateRange(DETECTIONS_URL, ROLES.platform_engineer);
+ waitForAlertsIndexToBeCreated();
+ });
+
+ beforeEach(() => {
+ // Index mapping is forced to return true as being outdated so that we get the
+ // need admin callouts being shown.
+ cy.intercept('GET', '/api/detection_engine/index', {
+ index_mapping_outdated: true,
+ name: '.siem-signals-default',
+ });
+ });
+
+ context('On Detections home page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineerUser(DETECTIONS_URL);
+ });
+
+ it('We show the need admin primary callout', () => {
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ });
+ });
+
+ context('On Rules Management page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ });
+
+ it('We show 1 primary callout of need admin', () => {
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ });
+ });
+
+ context('On Rule Details page', () => {
+ beforeEach(() => {
+ createCustomRule(newRule);
+ loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ waitForPageTitleToBeShown();
+ goToRuleDetails();
+ });
+
+ afterEach(() => {
+ deleteCustomRule();
+ });
+
+ it('We show 1 primary callout', () => {
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ });
+ });
+});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly.spec.ts
index c88697502ed08..1371f2cc4738e 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly.spec.ts
@@ -37,6 +37,7 @@ const waitForPageTitleToBeShown = () => {
describe('Detections > Callouts indicating read-only access to resources', () => {
const ALERTS_CALLOUT = 'read-only-access-to-alerts';
const RULES_CALLOUT = 'read-only-access-to-rules';
+ const NEED_ADMIN_FOR_UPDATE_CALLOUT = 'need-admin-for-update-rules';
before(() => {
// First, we have to open the app on behalf of a privileged user in order to initialize it.
@@ -56,6 +57,7 @@ describe('Detections > Callouts indicating read-only access to resources', () =>
it('We show one primary callout', () => {
waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
});
context('When a user clicks Dismiss on the callout', () => {
@@ -75,6 +77,7 @@ describe('Detections > Callouts indicating read-only access to resources', () =>
it('We show one primary callout', () => {
waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
});
context('When a user clicks Dismiss on the callout', () => {
@@ -102,24 +105,28 @@ describe('Detections > Callouts indicating read-only access to resources', () =>
it('We show two primary callouts', () => {
waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
});
context('When a user clicks Dismiss on the callouts', () => {
it('We hide them and persist the dismissal', () => {
waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
dismissCallOut(ALERTS_CALLOUT);
reloadPage();
getCallOut(ALERTS_CALLOUT).should('not.exist');
getCallOut(RULES_CALLOUT).should('be.visible');
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
dismissCallOut(RULES_CALLOUT);
reloadPage();
getCallOut(ALERTS_CALLOUT).should('not.exist');
getCallOut(RULES_CALLOUT).should('not.exist');
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
});
});
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts
new file mode 100644
index 0000000000000..4406190aaa3f2
--- /dev/null
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts
@@ -0,0 +1,143 @@
+/*
+ * 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 { ROLES } from '../../../common/test';
+import { DETECTIONS_RULE_MANAGEMENT_URL, DETECTIONS_URL } from '../../urls/navigation';
+import { newRule } from '../../objects/rule';
+import { PAGE_TITLE } from '../../screens/common/page';
+
+import {
+ login,
+ loginAndWaitForPageWithoutDateRange,
+ waitForPageWithoutDateRange,
+} from '../../tasks/login';
+import { waitForAlertsIndexToBeCreated } from '../../tasks/alerts';
+import { goToRuleDetails } from '../../tasks/alerts_detection_rules';
+import { createCustomRule, deleteCustomRule } from '../../tasks/api_calls/rules';
+import { getCallOut, waitForCallOutToBeShown, dismissCallOut } from '../../tasks/common/callouts';
+import { cleanKibana } from '../../tasks/common';
+
+const loadPageAsReadOnlyUser = (url: string) => {
+ waitForPageWithoutDateRange(url, ROLES.reader);
+ waitForPageTitleToBeShown();
+};
+
+const reloadPage = () => {
+ cy.reload();
+ waitForPageTitleToBeShown();
+};
+
+const waitForPageTitleToBeShown = () => {
+ cy.get(PAGE_TITLE).should('be.visible');
+};
+
+describe('Detections > Need Admin Callouts indicating an admin is needed to migrate the alert data set', () => {
+ const ALERTS_CALLOUT = 'read-only-access-to-alerts';
+ const RULES_CALLOUT = 'read-only-access-to-rules';
+ const NEED_ADMIN_FOR_UPDATE_CALLOUT = 'need-admin-for-update-rules';
+
+ before(() => {
+ // First, we have to open the app on behalf of a privileged user in order to initialize it.
+ // Otherwise the app will be disabled and show a "welcome"-like page.
+ cleanKibana();
+ loginAndWaitForPageWithoutDateRange(DETECTIONS_URL, ROLES.platform_engineer);
+ waitForAlertsIndexToBeCreated();
+
+ // After that we can login as a read-only user.
+ login(ROLES.reader);
+ });
+
+ beforeEach(() => {
+ // Index mapping is forced to return true as being outdated so that we get the
+ // need admin callouts being shown.
+ cy.intercept('GET', '/api/detection_engine/index', {
+ index_mapping_outdated: true,
+ name: '.siem-signals-default',
+ });
+ });
+
+ context('On Detections home page', () => {
+ beforeEach(() => {
+ loadPageAsReadOnlyUser(DETECTIONS_URL);
+ });
+
+ it('We show the alerts and admin primary callout', () => {
+ waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+ });
+
+ context('When a user clicks Dismiss on the callout', () => {
+ it('We hide it and persist the dismissal but still show the admin callout', () => {
+ waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
+ dismissCallOut(ALERTS_CALLOUT);
+ reloadPage();
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+ });
+ });
+ });
+
+ context('On Rules Management page', () => {
+ beforeEach(() => {
+ loadPageAsReadOnlyUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ });
+
+ it('We show two primary callouts of the alert and the admin', () => {
+ waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+ });
+
+ context('When a user clicks Dismiss on the callout', () => {
+ it('We hide it and persist the dismissal', () => {
+ waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
+ dismissCallOut(RULES_CALLOUT);
+ reloadPage();
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+ });
+ });
+ });
+
+ context('On Rule Details page', () => {
+ beforeEach(() => {
+ createCustomRule(newRule);
+ loadPageAsReadOnlyUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ waitForPageTitleToBeShown();
+ goToRuleDetails();
+ });
+
+ afterEach(() => {
+ deleteCustomRule();
+ });
+
+ it('We show three primary callouts', () => {
+ waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
+ waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+ });
+
+ context('When a user clicks Dismiss on the callouts', () => {
+ it('We hide them and persist the dismissal', () => {
+ waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
+ waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+
+ dismissCallOut(ALERTS_CALLOUT);
+ reloadPage();
+
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('be.visible');
+
+ dismissCallOut(RULES_CALLOUT);
+ reloadPage();
+
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+ });
+ });
+ });
+});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_t1_analyst.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_t1_analyst.spec.ts
new file mode 100644
index 0000000000000..9892e3a27fb3a
--- /dev/null
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_t1_analyst.spec.ts
@@ -0,0 +1,84 @@
+/*
+ * 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 { ROLES } from '../../../common/test';
+import { DETECTIONS_RULE_MANAGEMENT_URL, DETECTIONS_URL } from '../../urls/navigation';
+import { newRule } from '../../objects/rule';
+import { PAGE_TITLE } from '../../screens/common/page';
+
+import {
+ loginAndWaitForPageWithoutDateRange,
+ waitForPageWithoutDateRange,
+} from '../../tasks/login';
+import { waitForAlertsIndexToBeCreated } from '../../tasks/alerts';
+import { goToRuleDetails } from '../../tasks/alerts_detection_rules';
+import { createCustomRule, deleteCustomRule } from '../../tasks/api_calls/rules';
+import { getCallOut } from '../../tasks/common/callouts';
+import { cleanKibana } from '../../tasks/common';
+
+const loadPageAsPlatformEngineerUser = (url: string) => {
+ waitForPageWithoutDateRange(url, ROLES.t1_analyst);
+ waitForPageTitleToBeShown();
+};
+
+const waitForPageTitleToBeShown = () => {
+ cy.get(PAGE_TITLE).should('be.visible');
+};
+
+describe('Detections > Need Admin Callouts indicating an admin is needed to migrate the alert data set', () => {
+ const NEED_ADMIN_FOR_UPDATE_CALLOUT = 'need-admin-for-update-rules';
+ const ALERTS_CALLOUT = 'read-only-access-to-alerts';
+ const RULES_CALLOUT = 'read-only-access-to-rules';
+
+ before(() => {
+ cleanKibana();
+ loginAndWaitForPageWithoutDateRange(DETECTIONS_URL, ROLES.t1_analyst);
+ waitForAlertsIndexToBeCreated();
+ });
+
+ context('On Detections home page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineerUser(DETECTIONS_URL);
+ });
+
+ it('We show no callouts', () => {
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
+ });
+ });
+
+ context('On Rules Management page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ });
+
+ it('We show no callouts', () => {
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
+ });
+ });
+
+ context('On Rule Details page', () => {
+ beforeEach(() => {
+ createCustomRule(newRule);
+ loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ waitForPageTitleToBeShown();
+ goToRuleDetails();
+ });
+
+ afterEach(() => {
+ deleteCustomRule();
+ });
+
+ it('We show no callouts', () => {
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
+ });
+ });
+});
diff --git a/x-pack/plugins/security_solution/public/common/components/callouts/callout.test.tsx b/x-pack/plugins/security_solution/public/common/components/callouts/callout.test.tsx
new file mode 100644
index 0000000000000..8b4c4e6d5c800
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/common/components/callouts/callout.test.tsx
@@ -0,0 +1,112 @@
+/*
+ * 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 { mount } from 'enzyme';
+import React from 'react';
+import { CallOut, CallOutMessage } from '.';
+import { TestProviders } from '../../mock';
+
+describe('callout', () => {
+ let message: CallOutMessage = {
+ type: 'primary',
+ id: 'some-id',
+ title: 'title',
+ description: <>{'some description'}>,
+ };
+
+ beforeEach(() => {
+ message = {
+ type: 'primary',
+ id: 'some-id',
+ title: 'title',
+ description: <>{'some description'}>,
+ };
+ });
+
+ afterEach(() => {
+ jest.resetAllMocks();
+ });
+
+ test('renders the callout data-test-subj from the given id', () => {
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-some-id"]')).toEqual(true);
+ });
+
+ test('renders the callout dismiss button by default', () => {
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-dismiss-btn"]')).toEqual(true);
+ });
+
+ test('renders the callout dismiss button if given an explicit true to enable it', () => {
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-dismiss-btn"]')).toEqual(true);
+ });
+
+ test('Does NOT render the callout dismiss button if given an explicit false to disable it', () => {
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-dismiss-btn"]')).toEqual(false);
+ });
+
+ test('onDismiss callback operates when dismiss button is clicked', () => {
+ const onDismiss = jest.fn();
+ const wrapper = mount(
+
+
+
+ );
+ wrapper.find('[data-test-subj="callout-dismiss-btn"]').first().simulate('click');
+ expect(onDismiss).toBeCalledWith(message);
+ });
+
+ test('dismissButtonText can be set', () => {
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.find('[data-test-subj="callout-dismiss-btn"]').first().text()).toEqual(
+ 'Some other text'
+ );
+ });
+
+ test('a default icon type of "iInCircle" will be chosen if no iconType is set and the message type is "primary"', () => {
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.find('[data-test-subj="callout-some-id"]').first().prop('iconType')).toEqual(
+ 'iInCircle'
+ );
+ });
+
+ test('icon type can be changed from the type within the message', () => {
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.find('[data-test-subj="callout-some-id"]').first().prop('iconType')).toEqual(
+ 'something_else'
+ );
+ });
+});
diff --git a/x-pack/plugins/security_solution/public/common/components/callouts/callout.tsx b/x-pack/plugins/security_solution/public/common/components/callouts/callout.tsx
index 1eb048f7dd24e..1af59f9ef64ed 100644
--- a/x-pack/plugins/security_solution/public/common/components/callouts/callout.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/callouts/callout.tsx
@@ -8,7 +8,6 @@ import React, { FC, memo } from 'react';
import { EuiCallOut } from '@elastic/eui';
import { CallOutType, CallOutMessage } from './callout_types';
-import { CallOutDescription } from './callout_description';
import { CallOutDismissButton } from './callout_dismiss_button';
export interface CallOutProps {
@@ -16,6 +15,7 @@ export interface CallOutProps {
iconType?: string;
dismissButtonText?: string;
onDismiss?: (message: CallOutMessage) => void;
+ showDismissButton?: boolean;
}
const CallOutComponent: FC = ({
@@ -23,8 +23,9 @@ const CallOutComponent: FC = ({
iconType,
dismissButtonText,
onDismiss,
+ showDismissButton = true,
}) => {
- const { type, id, title } = message;
+ const { type, id, title, description } = message;
const finalIconType = iconType ?? getDefaultIconType(type);
return (
@@ -35,8 +36,10 @@ const CallOutComponent: FC = ({
data-test-subj={`callout-${id}`}
data-test-messages={`[${id}]`}
>
-
-
+ {description}
+ {showDismissButton && (
+
+ )}
);
};
@@ -51,8 +54,6 @@ const getDefaultIconType = (type: CallOutType): string => {
return 'help';
case 'danger':
return 'alert';
- default:
- return '';
}
};
diff --git a/x-pack/plugins/security_solution/public/common/components/callouts/callout_description.tsx b/x-pack/plugins/security_solution/public/common/components/callouts/callout_description.tsx
deleted file mode 100644
index d8b419f02d631..0000000000000
--- a/x-pack/plugins/security_solution/public/common/components/callouts/callout_description.tsx
+++ /dev/null
@@ -1,25 +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 React, { FC } from 'react';
-import { EuiDescriptionList } from '@elastic/eui';
-import { CallOutMessage } from './callout_types';
-
-export interface CallOutDescriptionProps {
- messages: CallOutMessage | CallOutMessage[];
-}
-
-export const CallOutDescription: FC = ({ messages }) => {
- if (!Array.isArray(messages)) {
- return messages.description;
- }
-
- if (messages.length < 1) {
- return null;
- }
-
- return ;
-};
diff --git a/x-pack/plugins/security_solution/public/common/components/callouts/callout_persistent_switcher.tsx b/x-pack/plugins/security_solution/public/common/components/callouts/callout_persistent_switcher.tsx
new file mode 100644
index 0000000000000..072e9ba5b288a
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/common/components/callouts/callout_persistent_switcher.tsx
@@ -0,0 +1,23 @@
+/*
+ * 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 React, { FC, memo } from 'react';
+
+import { CallOutMessage } from './callout_types';
+import { CallOut } from './callout';
+
+export interface CallOutPersistentSwitcherProps {
+ condition: boolean;
+ message: CallOutMessage;
+}
+
+const CallOutPersistentSwitcherComponent: FC = ({
+ condition,
+ message,
+}): JSX.Element | null =>
+ condition ? : null;
+
+export const CallOutPersistentSwitcher = memo(CallOutPersistentSwitcherComponent);
diff --git a/x-pack/plugins/security_solution/public/common/components/callouts/callout_types.ts b/x-pack/plugins/security_solution/public/common/components/callouts/callout_types.ts
index c72fe487af99b..1768038a92e30 100644
--- a/x-pack/plugins/security_solution/public/common/components/callouts/callout_types.ts
+++ b/x-pack/plugins/security_solution/public/common/components/callouts/callout_types.ts
@@ -4,7 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export type CallOutType = 'primary' | 'success' | 'warning' | 'danger';
+import { EuiCallOutProps } from '@elastic/eui';
+
+export type CallOutType = NonNullable;
export interface CallOutMessage {
type: CallOutType;
diff --git a/x-pack/plugins/security_solution/public/common/components/callouts/index.ts b/x-pack/plugins/security_solution/public/common/components/callouts/index.ts
index 8b636ce1bfae9..a3cd2fb7c1619 100644
--- a/x-pack/plugins/security_solution/public/common/components/callouts/index.ts
+++ b/x-pack/plugins/security_solution/public/common/components/callouts/index.ts
@@ -7,3 +7,4 @@
export * from './callout_switcher';
export * from './callout_types';
export * from './callout';
+export * from './callout_persistent_switcher';
diff --git a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx
new file mode 100644
index 0000000000000..1cf1d1bd53f0e
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx
@@ -0,0 +1,64 @@
+/*
+ * 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 { mount } from 'enzyme';
+import React from 'react';
+import { TestProviders } from '../../../../common/mock';
+import { NeedAdminForUpdateRulesCallOut } from '.';
+import * as userInfo from '../../user_info';
+
+describe('need_admin_for_update_callout', () => {
+ afterEach(() => {
+ jest.resetAllMocks();
+ });
+
+ test('renders when signalIndexMappingOutdated is true', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: true }]));
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(true);
+ });
+
+ test('Does not render a button as this is always persistent', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: true }]));
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-dismiss-btn"]')).toEqual(false);
+ });
+
+ test('Does NOT render when signalIndexMappingOutdated is false', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: false }]));
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(false);
+ });
+
+ test('Does NOT render when signalIndexMappingOutdated is null', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: null }]));
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(false);
+ });
+});
diff --git a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx
new file mode 100644
index 0000000000000..86cd8434cebe6
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx
@@ -0,0 +1,35 @@
+/*
+ * 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 React, { memo } from 'react';
+import { CallOutMessage, CallOutPersistentSwitcher } from '../../../../common/components/callouts';
+import { useUserData } from '../../user_info';
+
+import * as i18n from './translations';
+
+const needAdminForUpdateRulesMessage: CallOutMessage = {
+ type: 'primary',
+ id: 'need-admin-for-update-rules',
+ title: i18n.NEED_ADMIN_CALLOUT_TITLE,
+ description: i18n.needAdminForUpdateCallOutBody(),
+};
+
+/**
+ * Callout component that lets the user know that an administrator is needed for performing
+ * and auto-update of signals or not.
+ */
+const NeedAdminForUpdateCallOutComponent = (): JSX.Element => {
+ const [{ signalIndexMappingOutdated }] = useUserData();
+
+ return (
+
+ );
+};
+
+export const NeedAdminForUpdateRulesCallOut = memo(NeedAdminForUpdateCallOutComponent);
diff --git a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/translations.tsx b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/translations.tsx
new file mode 100644
index 0000000000000..9dd0fe30d9282
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/translations.tsx
@@ -0,0 +1,51 @@
+/*
+ * 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 React from 'react';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import {
+ SecuritySolutionRequirementsLink,
+ DetectionsRequirementsLink,
+} from '../../../../common/components/links_to_docs';
+
+export const NEED_ADMIN_CALLOUT_TITLE = i18n.translate(
+ 'xpack.securitySolution.detectionEngine.needAdminForUpdateCallOutBody.messageTitle',
+ {
+ defaultMessage: 'Administration permissions required for alert migration',
+ }
+);
+
+/**
+ * Returns the formatted message of the call out body as a JSX Element with both the message
+ * and two documentation links.
+ */
+export const needAdminForUpdateCallOutBody = (): JSX.Element => (
+
+
+
+ ),
+ docs: (
+
+ ),
+ }}
+ />
+);
diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx
index e6cf858b7fb5d..8202b52366b09 100644
--- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx
+++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx
@@ -52,6 +52,7 @@ import { timelineDefaults } from '../../../timelines/store/timeline/defaults';
import { buildShowBuildingBlockFilter } from '../../components/alerts_table/default_config';
import { useSourcererScope } from '../../../common/containers/sourcerer';
import { SourcererScopeName } from '../../../common/store/sourcerer/model';
+import { NeedAdminForUpdateRulesCallOut } from '../../components/callouts/need_admin_for_update_callout';
/**
* Need a 100% height here to account for the graph/analyze tool, which sets no explicit height parameters, but fills the available space.
@@ -192,6 +193,7 @@ const DetectionEnginePageComponent = () => {
<>
{hasEncryptionKey != null && !hasEncryptionKey && }
+
{indicesExist ? (
diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx
index 78c1732f30ef4..c61a4002ad3d7 100644
--- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx
+++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx
@@ -102,6 +102,7 @@ import * as detectionI18n from '../../translations';
import * as ruleI18n from '../translations';
import * as i18n from './translations';
import { isTab } from '../../../../../common/components/accessibility/helpers';
+import { NeedAdminForUpdateRulesCallOut } from '../../../../components/callouts/need_admin_for_update_callout';
/**
* Need a 100% height here to account for the graph/analyze tool, which sets no explicit height parameters, but fills the available space.
@@ -467,6 +468,7 @@ const RuleDetailsPageComponent = () => {
return (
<>
+
{indicesExist ? (
diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/index.tsx
index 9423604e546e9..a7a08dee670ff 100644
--- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/index.tsx
+++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/index.tsx
@@ -34,6 +34,7 @@ import * as i18n from './translations';
import { SecurityPageName } from '../../../../app/types';
import { LinkButton } from '../../../../common/components/links';
import { useFormatUrl } from '../../../../common/components/link_to';
+import { NeedAdminForUpdateRulesCallOut } from '../../../components/callouts/need_admin_for_update_callout';
type Func = () => Promise;
@@ -157,6 +158,7 @@ const RulesPageComponent: React.FC = () => {
return (
<>
+
Date: Wed, 3 Feb 2021 23:00:57 -0700
Subject: [PATCH 2/8] Updated license headers
---
.../alerts_detection_callouts_platform_engineer.ts | 5 +++--
..._detection_callouts_platform_engineer_need_admin.spec.ts | 5 +++--
.../alerts_detection_callouts_readonly_need_admin.spec.ts | 5 +++--
.../alerts_detection_callouts_t1_analyst.spec.ts | 5 +++--
.../public/common/components/callouts/callout.test.tsx | 5 +++--
.../components/callouts/callout_persistent_switcher.tsx | 5 +++--
.../callouts/need_admin_for_update_callout/index.test.tsx | 6 ++++--
.../callouts/need_admin_for_update_callout/index.tsx | 5 +++--
.../callouts/need_admin_for_update_callout/translations.tsx | 5 +++--
9 files changed, 28 insertions(+), 18 deletions(-)
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer.ts
index fc1ee8c17a7af..eafb1aefba1fe 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer.ts
@@ -1,7 +1,8 @@
/*
* 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.
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
*/
import { ROLES } from '../../../common/test';
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts
index 3645854e67468..d8bf78cbd2017 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts
@@ -1,7 +1,8 @@
/*
* 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.
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
*/
import { ROLES } from '../../../common/test';
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts
index 4406190aaa3f2..6fedfb942965d 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts
@@ -1,7 +1,8 @@
/*
* 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.
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
*/
import { ROLES } from '../../../common/test';
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_t1_analyst.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_t1_analyst.spec.ts
index 9892e3a27fb3a..b558405185f7e 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_t1_analyst.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_t1_analyst.spec.ts
@@ -1,7 +1,8 @@
/*
* 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.
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
*/
import { ROLES } from '../../../common/test';
diff --git a/x-pack/plugins/security_solution/public/common/components/callouts/callout.test.tsx b/x-pack/plugins/security_solution/public/common/components/callouts/callout.test.tsx
index 8b4c4e6d5c800..d6a4b8c8afa1a 100644
--- a/x-pack/plugins/security_solution/public/common/components/callouts/callout.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/callouts/callout.test.tsx
@@ -1,7 +1,8 @@
/*
* 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.
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
*/
import { mount } from 'enzyme';
diff --git a/x-pack/plugins/security_solution/public/common/components/callouts/callout_persistent_switcher.tsx b/x-pack/plugins/security_solution/public/common/components/callouts/callout_persistent_switcher.tsx
index 072e9ba5b288a..5b67410bb904a 100644
--- a/x-pack/plugins/security_solution/public/common/components/callouts/callout_persistent_switcher.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/callouts/callout_persistent_switcher.tsx
@@ -1,7 +1,8 @@
/*
* 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.
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
*/
import React, { FC, memo } from 'react';
diff --git a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx
index 1cf1d1bd53f0e..364320859676b 100644
--- a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx
@@ -1,8 +1,10 @@
/*
* 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.
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
*/
+
import { mount } from 'enzyme';
import React from 'react';
import { TestProviders } from '../../../../common/mock';
diff --git a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx
index 86cd8434cebe6..83f800529a8f1 100644
--- a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx
@@ -1,7 +1,8 @@
/*
* 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.
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
*/
import React, { memo } from 'react';
diff --git a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/translations.tsx b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/translations.tsx
index 9dd0fe30d9282..a2fd45e933c14 100644
--- a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/translations.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/translations.tsx
@@ -1,7 +1,8 @@
/*
* 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.
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
*/
import React from 'react';
From b715ed825b3e065c33ef1f4a3f971953e39e83bc Mon Sep 17 00:00:00 2001
From: FrankHassanabad
Date: Wed, 3 Feb 2021 23:11:58 -0700
Subject: [PATCH 3/8] Updated some wording
---
...erts_detection_callouts_platform_engineer_need_admin.spec.ts | 2 +-
.../alerts_detection_callouts_readonly_need_admin.spec.ts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts
index d8bf78cbd2017..51f4ce24cee66 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts
@@ -41,7 +41,7 @@ describe('Detections > Need Admin Callouts indicating an admin is needed to migr
});
beforeEach(() => {
- // Index mapping is forced to return true as being outdated so that we get the
+ // Index mapping outdated is forced to return true as being outdated so that we get the
// need admin callouts being shown.
cy.intercept('GET', '/api/detection_engine/index', {
index_mapping_outdated: true,
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts
index 6fedfb942965d..ae769c7228537 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts
@@ -52,7 +52,7 @@ describe('Detections > Need Admin Callouts indicating an admin is needed to migr
});
beforeEach(() => {
- // Index mapping is forced to return true as being outdated so that we get the
+ // Index mapping outdated is forced to return true as being outdated so that we get the
// need admin callouts being shown.
cy.intercept('GET', '/api/detection_engine/index', {
index_mapping_outdated: true,
From 03404135874bb1ad4393bb86f200b0cd287b5554 Mon Sep 17 00:00:00 2001
From: FrankHassanabad
Date: Fri, 5 Feb 2021 13:45:45 -0700
Subject: [PATCH 4/8] Fixed it so that the warning banner does not show up
whenever you have the priviledges to migrate the index in which case should
be happening
---
...louts_platform_engineer_need_admin.spec.ts | 8 +-
...on_callouts_soc_manager_need_admin.spec.ts | 94 ++++++++
.../index.test.tsx | 211 ++++++++++++++----
.../need_admin_for_update_callout/index.tsx | 17 +-
4 files changed, 282 insertions(+), 48 deletions(-)
create mode 100644 x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_soc_manager_need_admin.spec.ts
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts
index 51f4ce24cee66..8320944f665f3 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts
@@ -17,7 +17,7 @@ import {
import { waitForAlertsIndexToBeCreated } from '../../tasks/alerts';
import { goToRuleDetails } from '../../tasks/alerts_detection_rules';
import { createCustomRule, deleteCustomRule } from '../../tasks/api_calls/rules';
-import { getCallOut, waitForCallOutToBeShown } from '../../tasks/common/callouts';
+import { getCallOut } from '../../tasks/common/callouts';
import { cleanKibana } from '../../tasks/common';
const loadPageAsPlatformEngineerUser = (url: string) => {
@@ -55,9 +55,9 @@ describe('Detections > Need Admin Callouts indicating an admin is needed to migr
});
it('We show the need admin primary callout', () => {
- waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
getCallOut(ALERTS_CALLOUT).should('not.exist');
getCallOut(RULES_CALLOUT).should('not.exist');
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
});
});
@@ -67,9 +67,9 @@ describe('Detections > Need Admin Callouts indicating an admin is needed to migr
});
it('We show 1 primary callout of need admin', () => {
- waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
getCallOut(ALERTS_CALLOUT).should('not.exist');
getCallOut(RULES_CALLOUT).should('not.exist');
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
});
});
@@ -86,9 +86,9 @@ describe('Detections > Need Admin Callouts indicating an admin is needed to migr
});
it('We show 1 primary callout', () => {
- waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
getCallOut(ALERTS_CALLOUT).should('not.exist');
getCallOut(RULES_CALLOUT).should('not.exist');
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
});
});
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_soc_manager_need_admin.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_soc_manager_need_admin.spec.ts
new file mode 100644
index 0000000000000..cb4658f524777
--- /dev/null
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_soc_manager_need_admin.spec.ts
@@ -0,0 +1,94 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { ROLES } from '../../../common/test';
+import { DETECTIONS_RULE_MANAGEMENT_URL, DETECTIONS_URL } from '../../urls/navigation';
+import { newRule } from '../../objects/rule';
+import { PAGE_TITLE } from '../../screens/common/page';
+
+import {
+ loginAndWaitForPageWithoutDateRange,
+ waitForPageWithoutDateRange,
+} from '../../tasks/login';
+import { waitForAlertsIndexToBeCreated } from '../../tasks/alerts';
+import { goToRuleDetails } from '../../tasks/alerts_detection_rules';
+import { createCustomRule, deleteCustomRule } from '../../tasks/api_calls/rules';
+import { getCallOut, waitForCallOutToBeShown } from '../../tasks/common/callouts';
+import { cleanKibana } from '../../tasks/common';
+
+const loadPageAsPlatformEngineerUser = (url: string) => {
+ waitForPageWithoutDateRange(url, ROLES.soc_manager);
+ waitForPageTitleToBeShown();
+};
+
+const waitForPageTitleToBeShown = () => {
+ cy.get(PAGE_TITLE).should('be.visible');
+};
+
+describe('Detections > Need Admin Callouts indicating an admin is needed to migrate the alert data set', () => {
+ const NEED_ADMIN_FOR_UPDATE_CALLOUT = 'need-admin-for-update-rules';
+ const ALERTS_CALLOUT = 'read-only-access-to-alerts';
+ const RULES_CALLOUT = 'read-only-access-to-rules';
+
+ before(() => {
+ cleanKibana();
+ loginAndWaitForPageWithoutDateRange(DETECTIONS_URL, ROLES.soc_manager);
+ waitForAlertsIndexToBeCreated();
+ });
+
+ beforeEach(() => {
+ // Index mapping outdated is forced to return true as being outdated so that we get the
+ // need admin callouts being shown.
+ cy.intercept('GET', '/api/detection_engine/index', {
+ index_mapping_outdated: true,
+ name: '.siem-signals-default',
+ });
+ });
+
+ context('On Detections home page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineerUser(DETECTIONS_URL);
+ });
+
+ it('We show the need admin primary callout', () => {
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ });
+ });
+
+ context('On Rules Management page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ });
+
+ it('We show 1 primary callout of need admin', () => {
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ });
+ });
+
+ context('On Rule Details page', () => {
+ beforeEach(() => {
+ createCustomRule(newRule);
+ loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ waitForPageTitleToBeShown();
+ goToRuleDetails();
+ });
+
+ afterEach(() => {
+ deleteCustomRule();
+ });
+
+ it('We show 1 primary callout', () => {
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ });
+ });
+});
diff --git a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx
index 364320859676b..8798249ca5682 100644
--- a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx
@@ -16,51 +16,180 @@ describe('need_admin_for_update_callout', () => {
jest.resetAllMocks();
});
- test('renders when signalIndexMappingOutdated is true', () => {
- jest
- .spyOn(userInfo, 'useUserData')
- .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: true }]));
- const wrapper = mount(
-
-
-
- );
- expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(true);
- });
+ describe('hasIndexManage is "null"', () => {
+ const hasIndexManage = null;
+ test('renders when "signalIndexMappingOutdated" is true', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(
+ jest.fn().mockReturnValue([{ signalIndexMappingOutdated: true, hasIndexManage }])
+ );
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(
+ true
+ );
+ });
+
+ test('Does not render a button as this is always persistent', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: true }]));
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-dismiss-btn"]')).toEqual(false);
+ });
+
+ test('Does NOT render when signalIndexMappingOutdated is false', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: false }]));
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(
+ false
+ );
+ });
- test('Does not render a button as this is always persistent', () => {
- jest
- .spyOn(userInfo, 'useUserData')
- .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: true }]));
- const wrapper = mount(
-
-
-
- );
- expect(wrapper.exists('[data-test-subj="callout-dismiss-btn"]')).toEqual(false);
+ test('Does NOT render when signalIndexMappingOutdated is null', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: null }]));
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(
+ false
+ );
+ });
});
- test('Does NOT render when signalIndexMappingOutdated is false', () => {
- jest
- .spyOn(userInfo, 'useUserData')
- .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: false }]));
- const wrapper = mount(
-
-
-
- );
- expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(false);
+ describe('hasIndexManage is "false"', () => {
+ const hasIndexManage = false;
+ test('renders when "signalIndexMappingOutdated" is true', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(
+ jest.fn().mockReturnValue([{ signalIndexMappingOutdated: true, hasIndexManage }])
+ );
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(
+ true
+ );
+ });
+
+ test('Does not render a button as this is always persistent', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: true }]));
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-dismiss-btn"]')).toEqual(false);
+ });
+
+ test('Does NOT render when signalIndexMappingOutdated is false', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: false }]));
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(
+ false
+ );
+ });
+
+ test('Does NOT render when signalIndexMappingOutdated is null', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: null }]));
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(
+ false
+ );
+ });
});
- test('Does NOT render when signalIndexMappingOutdated is null', () => {
- jest
- .spyOn(userInfo, 'useUserData')
- .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: null }]));
- const wrapper = mount(
-
-
-
- );
- expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(false);
+ describe('hasIndexManage is "true"', () => {
+ const hasIndexManage = true;
+ test('Does not render when "signalIndexMappingOutdated" is true', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(
+ jest.fn().mockReturnValue([{ signalIndexMappingOutdated: true, hasIndexManage }])
+ );
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(
+ false
+ );
+ });
+
+ test('Does not render a button as this is always persistent', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: true }]));
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-dismiss-btn"]')).toEqual(false);
+ });
+
+ test('Does NOT render when signalIndexMappingOutdated is false', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: false }]));
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(
+ false
+ );
+ });
+
+ test('Does NOT render when signalIndexMappingOutdated is null', () => {
+ jest
+ .spyOn(userInfo, 'useUserData')
+ .mockImplementation(jest.fn().mockReturnValue([{ signalIndexMappingOutdated: null }]));
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(
+ false
+ );
+ });
});
});
diff --git a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx
index 83f800529a8f1..ea31c0c24ef08 100644
--- a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx
@@ -20,14 +20,25 @@ const needAdminForUpdateRulesMessage: CallOutMessage = {
/**
* Callout component that lets the user know that an administrator is needed for performing
- * and auto-update of signals or not.
+ * and auto-update of signals or not. For this component to render the user must:
+ * - Have the permissions to be able to read "signalIndexMappingOutdated" and that condition is "true"
+ * - Have the permissions to be able to read "hasIndexManage" and that condition is "false"
+ *
+ * If the user has the permissions to see that signalIndexMappingOutdated is true and that
+ * hasIndexManage is also true, then the user should be performing the update on the page which is
+ * why we do not show it for that condition.
*/
const NeedAdminForUpdateCallOutComponent = (): JSX.Element => {
- const [{ signalIndexMappingOutdated }] = useUserData();
+ const [{ signalIndexMappingOutdated, hasIndexManage }] = useUserData();
+
+ const signalIndexMappingIsOutdated =
+ signalIndexMappingOutdated != null && signalIndexMappingOutdated;
+
+ const userHasIndexManage = hasIndexManage != null && hasIndexManage;
return (
);
From 68b8cd17bfaee3a57cc276115f29bd43e7153667 Mon Sep 17 00:00:00 2001
From: FrankHassanabad
Date: Fri, 5 Feb 2021 14:03:00 -0700
Subject: [PATCH 5/8] Fixed wording by removing the dash in auto-migrate
---
.../callouts/need_admin_for_update_callout/translations.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/translations.tsx b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/translations.tsx
index a2fd45e933c14..791093788b8e1 100644
--- a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/translations.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/translations.tsx
@@ -33,7 +33,7 @@ export const needAdminForUpdateCallOutBody = (): JSX.Element => (
),
From e2be038a5c597f5b10c201c310c646aaeb8429cb Mon Sep 17 00:00:00 2001
From: FrankHassanabad
Date: Mon, 8 Feb 2021 21:55:25 -0700
Subject: [PATCH 6/8] Fixes from PR review
---
.../public/common/components/callouts/callout.tsx | 3 +++
1 file changed, 3 insertions(+)
diff --git a/x-pack/plugins/security_solution/public/common/components/callouts/callout.tsx b/x-pack/plugins/security_solution/public/common/components/callouts/callout.tsx
index 997589d548e93..2077e421c427a 100644
--- a/x-pack/plugins/security_solution/public/common/components/callouts/callout.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/callouts/callout.tsx
@@ -8,6 +8,7 @@
import React, { FC, memo } from 'react';
import { EuiCallOut } from '@elastic/eui';
+import { assertUnreachable } from '../../../../common/utility_types';
import { CallOutType, CallOutMessage } from './callout_types';
import { CallOutDismissButton } from './callout_dismiss_button';
@@ -55,6 +56,8 @@ const getDefaultIconType = (type: CallOutType): string => {
return 'help';
case 'danger':
return 'alert';
+ default:
+ return assertUnreachable(type);
}
};
From dc62dc7dcb09f57b18ce1659cb036cd0eebdc380 Mon Sep 17 00:00:00 2001
From: FrankHassanabad
Date: Tue, 9 Feb 2021 14:42:42 -0700
Subject: [PATCH 7/8] Updates from PR review
---
.../public/common/components/callouts/callout.test.tsx | 3 ++-
.../need_admin_for_update_callout/index.test.tsx | 6 +++---
.../callouts/need_admin_for_update_callout/index.tsx | 9 +++++++--
3 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/x-pack/plugins/security_solution/public/common/components/callouts/callout.test.tsx b/x-pack/plugins/security_solution/public/common/components/callouts/callout.test.tsx
index d6a4b8c8afa1a..f908a79361d0a 100644
--- a/x-pack/plugins/security_solution/public/common/components/callouts/callout.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/callouts/callout.test.tsx
@@ -7,8 +7,9 @@
import { mount } from 'enzyme';
import React from 'react';
-import { CallOut, CallOutMessage } from '.';
import { TestProviders } from '../../mock';
+import { CallOut } from './callout';
+import { CallOutMessage } from './callout_types';
describe('callout', () => {
let message: CallOutMessage = {
diff --git a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx
index 8798249ca5682..66b2bae98c1ae 100644
--- a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.test.tsx
@@ -7,8 +7,8 @@
import { mount } from 'enzyme';
import React from 'react';
+import { NeedAdminForUpdateRulesCallOut } from './index';
import { TestProviders } from '../../../../common/mock';
-import { NeedAdminForUpdateRulesCallOut } from '.';
import * as userInfo from '../../user_info';
describe('need_admin_for_update_callout', () => {
@@ -18,7 +18,7 @@ describe('need_admin_for_update_callout', () => {
describe('hasIndexManage is "null"', () => {
const hasIndexManage = null;
- test('renders when "signalIndexMappingOutdated" is true', () => {
+ test('Does NOT render when "signalIndexMappingOutdated" is true', () => {
jest
.spyOn(userInfo, 'useUserData')
.mockImplementation(
@@ -30,7 +30,7 @@ describe('need_admin_for_update_callout', () => {
);
expect(wrapper.exists('[data-test-subj="callout-need-admin-for-update-rules"]')).toEqual(
- true
+ false
);
});
diff --git a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx
index ea31c0c24ef08..fd0be8e002193 100644
--- a/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/callouts/need_admin_for_update_callout/index.tsx
@@ -24,6 +24,11 @@ const needAdminForUpdateRulesMessage: CallOutMessage = {
* - Have the permissions to be able to read "signalIndexMappingOutdated" and that condition is "true"
* - Have the permissions to be able to read "hasIndexManage" and that condition is "false"
*
+ * Some users do not have sufficient privileges to be able to determine if "signalIndexMappingOutdated"
+ * is outdated or not. Same could apply to "hasIndexManage". When users do not have enough permissions
+ * to determine if "signalIndexMappingOutdated" is true or false, the permissions system returns a "null"
+ * instead.
+ *
* If the user has the permissions to see that signalIndexMappingOutdated is true and that
* hasIndexManage is also true, then the user should be performing the update on the page which is
* why we do not show it for that condition.
@@ -34,11 +39,11 @@ const NeedAdminForUpdateCallOutComponent = (): JSX.Element => {
const signalIndexMappingIsOutdated =
signalIndexMappingOutdated != null && signalIndexMappingOutdated;
- const userHasIndexManage = hasIndexManage != null && hasIndexManage;
+ const userDoesntHaveIndexManage = hasIndexManage != null && !hasIndexManage;
return (
);
From efec9c301a319804c3bd48fe31f590dd2115a851 Mon Sep 17 00:00:00 2001
From: FrankHassanabad
Date: Tue, 16 Feb 2021 18:39:32 -0700
Subject: [PATCH 8/8] Fixes tests from PR feedback
---
.../security_solution/common/utility_types.ts | 6 +
..._detection_callouts_index_outdated.spec.ts | 196 ++++++++++++++++++
...ts_detection_callouts_platform_engineer.ts | 85 --------
...louts_platform_engineer_need_admin.spec.ts | 94 ---------
...alerts_detection_callouts_readonly.spec.ts | 154 +++++++++-----
...ction_callouts_readonly_need_admin.spec.ts | 144 -------------
...on_callouts_soc_manager_need_admin.spec.ts | 94 ---------
...erts_detection_callouts_t1_analyst.spec.ts | 85 --------
.../cypress/tasks/common/callouts.ts | 6 +-
.../factory/hosts/all/query.all_hosts.dsl.ts | 2 +-
10 files changed, 303 insertions(+), 563 deletions(-)
create mode 100644 x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_index_outdated.spec.ts
delete mode 100644 x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer.ts
delete mode 100644 x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts
delete mode 100644 x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts
delete mode 100644 x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_soc_manager_need_admin.spec.ts
delete mode 100644 x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_t1_analyst.spec.ts
diff --git a/x-pack/plugins/security_solution/common/utility_types.ts b/x-pack/plugins/security_solution/common/utility_types.ts
index 3c13e6af837bc..498b18dccaca5 100644
--- a/x-pack/plugins/security_solution/common/utility_types.ts
+++ b/x-pack/plugins/security_solution/common/utility_types.ts
@@ -36,6 +36,12 @@ export const stringEnum = (enumObj: T, enumName = 'enum') =>
*
* Optionally you can avoid the use of this by using early returns and TypeScript will clear your type checking without complaints
* but there are situations and times where this function might still be needed.
+ *
+ * If you see an error, DO NOT cast "as never" such as:
+ * assertUnreachable(x as never) // BUG IN YOUR CODE NOW AND IT WILL THROW DURING RUNTIME
+ * If you see code like that remove it, as that deactivates the intent of this utility.
+ * If you need to do that, then you should remove assertUnreachable from your code and
+ * use a default at the end of the switch instead.
* @param x Unreachable field
* @param message Message of error thrown
*/
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_index_outdated.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_index_outdated.spec.ts
new file mode 100644
index 0000000000000..1c6c604b84fbb
--- /dev/null
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_index_outdated.spec.ts
@@ -0,0 +1,196 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { ROLES } from '../../../common/test';
+import { DETECTIONS_RULE_MANAGEMENT_URL, DETECTIONS_URL } from '../../urls/navigation';
+import { newRule } from '../../objects/rule';
+import { PAGE_TITLE } from '../../screens/common/page';
+
+import {
+ login,
+ loginAndWaitForPageWithoutDateRange,
+ waitForPageWithoutDateRange,
+} from '../../tasks/login';
+import { waitForAlertsIndexToBeCreated } from '../../tasks/alerts';
+import { goToRuleDetails } from '../../tasks/alerts_detection_rules';
+import { createCustomRule, deleteCustomRule } from '../../tasks/api_calls/rules';
+import { getCallOut, waitForCallOutToBeShown } from '../../tasks/common/callouts';
+import { cleanKibana } from '../../tasks/common';
+
+const loadPageAsPlatformEngineerUser = (url: string) => {
+ waitForPageWithoutDateRange(url, ROLES.soc_manager);
+ waitForPageTitleToBeShown();
+};
+
+const waitForPageTitleToBeShown = () => {
+ cy.get(PAGE_TITLE).should('be.visible');
+};
+
+describe('Detections > Need Admin Callouts indicating an admin is needed to migrate the alert data set', () => {
+ const NEED_ADMIN_FOR_UPDATE_CALLOUT = 'need-admin-for-update-rules';
+
+ before(() => {
+ // First, we have to open the app on behalf of a privileged user in order to initialize it.
+ // Otherwise the app will be disabled and show a "welcome"-like page.
+ cleanKibana();
+ loginAndWaitForPageWithoutDateRange(DETECTIONS_URL, ROLES.platform_engineer);
+ waitForAlertsIndexToBeCreated();
+
+ // After that we can login as a soc manager.
+ login(ROLES.soc_manager);
+ });
+
+ context(
+ 'The users index_mapping_outdated is "true" and their admin callouts should show up',
+ () => {
+ beforeEach(() => {
+ // Index mapping outdated is forced to return true as being outdated so that we get the
+ // need admin callouts being shown.
+ cy.intercept('GET', '/api/detection_engine/index', {
+ index_mapping_outdated: true,
+ name: '.siem-signals-default',
+ });
+ });
+ context('On Detections home page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineerUser(DETECTIONS_URL);
+ });
+
+ it('We show the need admin primary callout', () => {
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+ });
+ });
+
+ context('On Rules Management page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ });
+
+ it('We show 1 primary callout of need admin', () => {
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+ });
+ });
+
+ context('On Rule Details page', () => {
+ beforeEach(() => {
+ createCustomRule(newRule);
+ loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ waitForPageTitleToBeShown();
+ goToRuleDetails();
+ });
+
+ afterEach(() => {
+ deleteCustomRule();
+ });
+
+ it('We show 1 primary callout', () => {
+ waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
+ });
+ });
+ }
+ );
+
+ context(
+ 'The users index_mapping_outdated is "false" and their admin callouts should not show up ',
+ () => {
+ beforeEach(() => {
+ // Index mapping outdated is forced to return true as being outdated so that we get the
+ // need admin callouts being shown.
+ cy.intercept('GET', '/api/detection_engine/index', {
+ index_mapping_outdated: false,
+ name: '.siem-signals-default',
+ });
+ });
+ context('On Detections home page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineerUser(DETECTIONS_URL);
+ });
+
+ it('We show the need admin primary callout', () => {
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
+ });
+ });
+
+ context('On Rules Management page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ });
+
+ it('We show 1 primary callout of need admin', () => {
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
+ });
+ });
+
+ context('On Rule Details page', () => {
+ beforeEach(() => {
+ createCustomRule(newRule);
+ loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ waitForPageTitleToBeShown();
+ goToRuleDetails();
+ });
+
+ afterEach(() => {
+ deleteCustomRule();
+ });
+
+ it('We show 1 primary callout', () => {
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
+ });
+ });
+ }
+ );
+
+ context(
+ 'The users index_mapping_outdated is "null" and their admin callouts should not show up ',
+ () => {
+ beforeEach(() => {
+ // Index mapping outdated is forced to return true as being outdated so that we get the
+ // need admin callouts being shown.
+ cy.intercept('GET', '/api/detection_engine/index', {
+ index_mapping_outdated: null,
+ name: '.siem-signals-default',
+ });
+ });
+ context('On Detections home page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineerUser(DETECTIONS_URL);
+ });
+
+ it('We show the need admin primary callout', () => {
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
+ });
+ });
+
+ context('On Rules Management page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ });
+
+ it('We show 1 primary callout of need admin', () => {
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
+ });
+ });
+
+ context('On Rule Details page', () => {
+ beforeEach(() => {
+ createCustomRule(newRule);
+ loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ waitForPageTitleToBeShown();
+ goToRuleDetails();
+ });
+
+ afterEach(() => {
+ deleteCustomRule();
+ });
+
+ it('We show 1 primary callout', () => {
+ getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
+ });
+ });
+ }
+ );
+});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer.ts
deleted file mode 100644
index eafb1aefba1fe..0000000000000
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer.ts
+++ /dev/null
@@ -1,85 +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
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ROLES } from '../../../common/test';
-import { DETECTIONS_RULE_MANAGEMENT_URL, DETECTIONS_URL } from '../../urls/navigation';
-import { newRule } from '../../objects/rule';
-import { PAGE_TITLE } from '../../screens/common/page';
-
-import {
- loginAndWaitForPageWithoutDateRange,
- waitForPageWithoutDateRange,
-} from '../../tasks/login';
-import { waitForAlertsIndexToBeCreated } from '../../tasks/alerts';
-import { goToRuleDetails } from '../../tasks/alerts_detection_rules';
-import { createCustomRule, deleteCustomRule } from '../../tasks/api_calls/rules';
-import { getCallOut } from '../../tasks/common/callouts';
-import { cleanKibana } from '../../tasks/common';
-
-const loadPageAsPlatformEngineerUser = (url: string) => {
- waitForPageWithoutDateRange(url, ROLES.platform_engineer);
- waitForPageTitleToBeShown();
-};
-
-const waitForPageTitleToBeShown = () => {
- cy.get(PAGE_TITLE).should('be.visible');
-};
-
-describe('Detections > Need Admin Callouts indicating an admin is needed to migrate the alert data set', () => {
- const NEED_ADMIN_FOR_UPDATE_CALLOUT = 'need-admin-for-update-rules';
- const ALERTS_CALLOUT = 'read-only-access-to-alerts';
- const RULES_CALLOUT = 'read-only-access-to-rules';
-
- before(() => {
- cleanKibana();
- loginAndWaitForPageWithoutDateRange(DETECTIONS_URL, ROLES.platform_engineer);
- waitForAlertsIndexToBeCreated();
- });
-
- context('On Detections home page', () => {
- beforeEach(() => {
- loadPageAsPlatformEngineerUser(DETECTIONS_URL);
- });
-
- it('We show no callouts', () => {
- getCallOut(ALERTS_CALLOUT).should('not.exist');
- getCallOut(RULES_CALLOUT).should('not.exist');
- getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
- });
- });
-
- context('On Rules Management page', () => {
- beforeEach(() => {
- loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
- });
-
- it('We show no callouts', () => {
- getCallOut(ALERTS_CALLOUT).should('not.exist');
- getCallOut(RULES_CALLOUT).should('not.exist');
- getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
- });
- });
-
- context('On Rule Details page', () => {
- beforeEach(() => {
- createCustomRule(newRule);
- loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
- waitForPageTitleToBeShown();
- goToRuleDetails();
- });
-
- afterEach(() => {
- deleteCustomRule();
- });
-
- it('We show no callouts', () => {
- getCallOut(ALERTS_CALLOUT).should('not.exist');
- getCallOut(RULES_CALLOUT).should('not.exist');
- getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
- });
- });
-});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts
deleted file mode 100644
index 8320944f665f3..0000000000000
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_platform_engineer_need_admin.spec.ts
+++ /dev/null
@@ -1,94 +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
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ROLES } from '../../../common/test';
-import { DETECTIONS_RULE_MANAGEMENT_URL, DETECTIONS_URL } from '../../urls/navigation';
-import { newRule } from '../../objects/rule';
-import { PAGE_TITLE } from '../../screens/common/page';
-
-import {
- loginAndWaitForPageWithoutDateRange,
- waitForPageWithoutDateRange,
-} from '../../tasks/login';
-import { waitForAlertsIndexToBeCreated } from '../../tasks/alerts';
-import { goToRuleDetails } from '../../tasks/alerts_detection_rules';
-import { createCustomRule, deleteCustomRule } from '../../tasks/api_calls/rules';
-import { getCallOut } from '../../tasks/common/callouts';
-import { cleanKibana } from '../../tasks/common';
-
-const loadPageAsPlatformEngineerUser = (url: string) => {
- waitForPageWithoutDateRange(url, ROLES.platform_engineer);
- waitForPageTitleToBeShown();
-};
-
-const waitForPageTitleToBeShown = () => {
- cy.get(PAGE_TITLE).should('be.visible');
-};
-
-describe('Detections > Need Admin Callouts indicating an admin is needed to migrate the alert data set', () => {
- const NEED_ADMIN_FOR_UPDATE_CALLOUT = 'need-admin-for-update-rules';
- const ALERTS_CALLOUT = 'read-only-access-to-alerts';
- const RULES_CALLOUT = 'read-only-access-to-rules';
-
- before(() => {
- cleanKibana();
- loginAndWaitForPageWithoutDateRange(DETECTIONS_URL, ROLES.platform_engineer);
- waitForAlertsIndexToBeCreated();
- });
-
- beforeEach(() => {
- // Index mapping outdated is forced to return true as being outdated so that we get the
- // need admin callouts being shown.
- cy.intercept('GET', '/api/detection_engine/index', {
- index_mapping_outdated: true,
- name: '.siem-signals-default',
- });
- });
-
- context('On Detections home page', () => {
- beforeEach(() => {
- loadPageAsPlatformEngineerUser(DETECTIONS_URL);
- });
-
- it('We show the need admin primary callout', () => {
- getCallOut(ALERTS_CALLOUT).should('not.exist');
- getCallOut(RULES_CALLOUT).should('not.exist');
- getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
- });
- });
-
- context('On Rules Management page', () => {
- beforeEach(() => {
- loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
- });
-
- it('We show 1 primary callout of need admin', () => {
- getCallOut(ALERTS_CALLOUT).should('not.exist');
- getCallOut(RULES_CALLOUT).should('not.exist');
- getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
- });
- });
-
- context('On Rule Details page', () => {
- beforeEach(() => {
- createCustomRule(newRule);
- loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
- waitForPageTitleToBeShown();
- goToRuleDetails();
- });
-
- afterEach(() => {
- deleteCustomRule();
- });
-
- it('We show 1 primary callout', () => {
- getCallOut(ALERTS_CALLOUT).should('not.exist');
- getCallOut(RULES_CALLOUT).should('not.exist');
- getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
- });
- });
-});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly.spec.ts
index 8f1ed00ffd10d..d807857cd72bd 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly.spec.ts
@@ -26,6 +26,11 @@ const loadPageAsReadOnlyUser = (url: string) => {
waitForPageTitleToBeShown();
};
+const loadPageAsPlatformEngineer = (url: string) => {
+ waitForPageWithoutDateRange(url, ROLES.platform_engineer);
+ waitForPageTitleToBeShown();
+};
+
const reloadPage = () => {
cy.reload();
waitForPageTitleToBeShown();
@@ -35,10 +40,9 @@ const waitForPageTitleToBeShown = () => {
cy.get(PAGE_TITLE).should('be.visible');
};
-describe('Detections > Callouts indicating read-only access to resources', () => {
+describe('Detections > Callouts', () => {
const ALERTS_CALLOUT = 'read-only-access-to-alerts';
const RULES_CALLOUT = 'read-only-access-to-rules';
- const NEED_ADMIN_FOR_UPDATE_CALLOUT = 'need-admin-for-update-rules';
before(() => {
// First, we have to open the app on behalf of a privileged user in order to initialize it.
@@ -51,83 +55,121 @@ describe('Detections > Callouts indicating read-only access to resources', () =>
login(ROLES.reader);
});
- context('On Detections home page', () => {
- beforeEach(() => {
- loadPageAsReadOnlyUser(DETECTIONS_URL);
- });
-
- it('We show one primary callout', () => {
- waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
- getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
- });
+ context('indicating read-only access to resources', () => {
+ context('On Detections home page', () => {
+ beforeEach(() => {
+ loadPageAsReadOnlyUser(DETECTIONS_URL);
+ });
- context('When a user clicks Dismiss on the callout', () => {
- it('We hide it and persist the dismissal', () => {
+ it('We show one primary callout', () => {
waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
- dismissCallOut(ALERTS_CALLOUT);
- reloadPage();
- getCallOut(ALERTS_CALLOUT).should('not.exist');
});
- });
- });
- context('On Rules Management page', () => {
- beforeEach(() => {
- loadPageAsReadOnlyUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ context('When a user clicks Dismiss on the callout', () => {
+ it('We hide it and persist the dismissal', () => {
+ waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
+ dismissCallOut(ALERTS_CALLOUT);
+ reloadPage();
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ });
+ });
});
- it('We show one primary callout', () => {
- waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
- getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
- });
+ context('On Rules Management page', () => {
+ beforeEach(() => {
+ loadPageAsReadOnlyUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ });
- context('When a user clicks Dismiss on the callout', () => {
- it('We hide it and persist the dismissal', () => {
+ it('We show one primary callout', () => {
waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
- dismissCallOut(RULES_CALLOUT);
- reloadPage();
- getCallOut(RULES_CALLOUT).should('not.exist');
});
- });
- });
- context('On Rule Details page', () => {
- beforeEach(() => {
- createCustomRule(newRule);
- loadPageAsReadOnlyUser(DETECTIONS_RULE_MANAGEMENT_URL);
- waitForPageTitleToBeShown();
- goToRuleDetails();
+ context('When a user clicks Dismiss on the callout', () => {
+ it('We hide it and persist the dismissal', () => {
+ waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
+ dismissCallOut(RULES_CALLOUT);
+ reloadPage();
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ });
+ });
});
- afterEach(() => {
- deleteCustomRule();
- });
+ context('On Rule Details page', () => {
+ beforeEach(() => {
+ createCustomRule(newRule);
+ loadPageAsReadOnlyUser(DETECTIONS_RULE_MANAGEMENT_URL);
+ waitForPageTitleToBeShown();
+ goToRuleDetails();
+ });
- it('We show two primary callouts', () => {
- waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
- waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
- getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
- });
+ afterEach(() => {
+ deleteCustomRule();
+ });
- context('When a user clicks Dismiss on the callouts', () => {
- it('We hide them and persist the dismissal', () => {
+ it('We show two primary callouts', () => {
waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
- getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
+ });
- dismissCallOut(ALERTS_CALLOUT);
- reloadPage();
+ context('When a user clicks Dismiss on the callouts', () => {
+ it('We hide them and persist the dismissal', () => {
+ waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
+ waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
+ dismissCallOut(ALERTS_CALLOUT);
+ reloadPage();
+
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('be.visible');
+
+ dismissCallOut(RULES_CALLOUT);
+ reloadPage();
+
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ });
+ });
+ });
+ });
+
+ context('indicating read-write access to resources', () => {
+ context('On Detections home page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineer(DETECTIONS_URL);
+ });
+
+ it('We show no callout', () => {
+ getCallOut(ALERTS_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ });
+ });
+
+ context('On Rules Management page', () => {
+ beforeEach(() => {
+ loadPageAsPlatformEngineer(DETECTIONS_RULE_MANAGEMENT_URL);
+ });
+
+ it('We show no callout', () => {
getCallOut(ALERTS_CALLOUT).should('not.exist');
- getCallOut(RULES_CALLOUT).should('be.visible');
- getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
+ getCallOut(RULES_CALLOUT).should('not.exist');
+ });
+ });
- dismissCallOut(RULES_CALLOUT);
- reloadPage();
+ context('On Rule Details page', () => {
+ beforeEach(() => {
+ createCustomRule(newRule);
+ loadPageAsPlatformEngineer(DETECTIONS_RULE_MANAGEMENT_URL);
+ waitForPageTitleToBeShown();
+ goToRuleDetails();
+ });
+
+ afterEach(() => {
+ deleteCustomRule();
+ });
+ it('We show no callouts', () => {
getCallOut(ALERTS_CALLOUT).should('not.exist');
getCallOut(RULES_CALLOUT).should('not.exist');
- getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
});
});
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts
deleted file mode 100644
index ae769c7228537..0000000000000
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_readonly_need_admin.spec.ts
+++ /dev/null
@@ -1,144 +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
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ROLES } from '../../../common/test';
-import { DETECTIONS_RULE_MANAGEMENT_URL, DETECTIONS_URL } from '../../urls/navigation';
-import { newRule } from '../../objects/rule';
-import { PAGE_TITLE } from '../../screens/common/page';
-
-import {
- login,
- loginAndWaitForPageWithoutDateRange,
- waitForPageWithoutDateRange,
-} from '../../tasks/login';
-import { waitForAlertsIndexToBeCreated } from '../../tasks/alerts';
-import { goToRuleDetails } from '../../tasks/alerts_detection_rules';
-import { createCustomRule, deleteCustomRule } from '../../tasks/api_calls/rules';
-import { getCallOut, waitForCallOutToBeShown, dismissCallOut } from '../../tasks/common/callouts';
-import { cleanKibana } from '../../tasks/common';
-
-const loadPageAsReadOnlyUser = (url: string) => {
- waitForPageWithoutDateRange(url, ROLES.reader);
- waitForPageTitleToBeShown();
-};
-
-const reloadPage = () => {
- cy.reload();
- waitForPageTitleToBeShown();
-};
-
-const waitForPageTitleToBeShown = () => {
- cy.get(PAGE_TITLE).should('be.visible');
-};
-
-describe('Detections > Need Admin Callouts indicating an admin is needed to migrate the alert data set', () => {
- const ALERTS_CALLOUT = 'read-only-access-to-alerts';
- const RULES_CALLOUT = 'read-only-access-to-rules';
- const NEED_ADMIN_FOR_UPDATE_CALLOUT = 'need-admin-for-update-rules';
-
- before(() => {
- // First, we have to open the app on behalf of a privileged user in order to initialize it.
- // Otherwise the app will be disabled and show a "welcome"-like page.
- cleanKibana();
- loginAndWaitForPageWithoutDateRange(DETECTIONS_URL, ROLES.platform_engineer);
- waitForAlertsIndexToBeCreated();
-
- // After that we can login as a read-only user.
- login(ROLES.reader);
- });
-
- beforeEach(() => {
- // Index mapping outdated is forced to return true as being outdated so that we get the
- // need admin callouts being shown.
- cy.intercept('GET', '/api/detection_engine/index', {
- index_mapping_outdated: true,
- name: '.siem-signals-default',
- });
- });
-
- context('On Detections home page', () => {
- beforeEach(() => {
- loadPageAsReadOnlyUser(DETECTIONS_URL);
- });
-
- it('We show the alerts and admin primary callout', () => {
- waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
- waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
- });
-
- context('When a user clicks Dismiss on the callout', () => {
- it('We hide it and persist the dismissal but still show the admin callout', () => {
- waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
- dismissCallOut(ALERTS_CALLOUT);
- reloadPage();
- getCallOut(ALERTS_CALLOUT).should('not.exist');
- waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
- });
- });
- });
-
- context('On Rules Management page', () => {
- beforeEach(() => {
- loadPageAsReadOnlyUser(DETECTIONS_RULE_MANAGEMENT_URL);
- });
-
- it('We show two primary callouts of the alert and the admin', () => {
- waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
- waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
- });
-
- context('When a user clicks Dismiss on the callout', () => {
- it('We hide it and persist the dismissal', () => {
- waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
- dismissCallOut(RULES_CALLOUT);
- reloadPage();
- getCallOut(RULES_CALLOUT).should('not.exist');
- waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
- });
- });
- });
-
- context('On Rule Details page', () => {
- beforeEach(() => {
- createCustomRule(newRule);
- loadPageAsReadOnlyUser(DETECTIONS_RULE_MANAGEMENT_URL);
- waitForPageTitleToBeShown();
- goToRuleDetails();
- });
-
- afterEach(() => {
- deleteCustomRule();
- });
-
- it('We show three primary callouts', () => {
- waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
- waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
- waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
- });
-
- context('When a user clicks Dismiss on the callouts', () => {
- it('We hide them and persist the dismissal', () => {
- waitForCallOutToBeShown(ALERTS_CALLOUT, 'primary');
- waitForCallOutToBeShown(RULES_CALLOUT, 'primary');
- waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
-
- dismissCallOut(ALERTS_CALLOUT);
- reloadPage();
-
- getCallOut(ALERTS_CALLOUT).should('not.exist');
- getCallOut(RULES_CALLOUT).should('be.visible');
-
- dismissCallOut(RULES_CALLOUT);
- reloadPage();
-
- getCallOut(ALERTS_CALLOUT).should('not.exist');
- getCallOut(RULES_CALLOUT).should('not.exist');
- waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
- });
- });
- });
-});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_soc_manager_need_admin.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_soc_manager_need_admin.spec.ts
deleted file mode 100644
index cb4658f524777..0000000000000
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_soc_manager_need_admin.spec.ts
+++ /dev/null
@@ -1,94 +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
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ROLES } from '../../../common/test';
-import { DETECTIONS_RULE_MANAGEMENT_URL, DETECTIONS_URL } from '../../urls/navigation';
-import { newRule } from '../../objects/rule';
-import { PAGE_TITLE } from '../../screens/common/page';
-
-import {
- loginAndWaitForPageWithoutDateRange,
- waitForPageWithoutDateRange,
-} from '../../tasks/login';
-import { waitForAlertsIndexToBeCreated } from '../../tasks/alerts';
-import { goToRuleDetails } from '../../tasks/alerts_detection_rules';
-import { createCustomRule, deleteCustomRule } from '../../tasks/api_calls/rules';
-import { getCallOut, waitForCallOutToBeShown } from '../../tasks/common/callouts';
-import { cleanKibana } from '../../tasks/common';
-
-const loadPageAsPlatformEngineerUser = (url: string) => {
- waitForPageWithoutDateRange(url, ROLES.soc_manager);
- waitForPageTitleToBeShown();
-};
-
-const waitForPageTitleToBeShown = () => {
- cy.get(PAGE_TITLE).should('be.visible');
-};
-
-describe('Detections > Need Admin Callouts indicating an admin is needed to migrate the alert data set', () => {
- const NEED_ADMIN_FOR_UPDATE_CALLOUT = 'need-admin-for-update-rules';
- const ALERTS_CALLOUT = 'read-only-access-to-alerts';
- const RULES_CALLOUT = 'read-only-access-to-rules';
-
- before(() => {
- cleanKibana();
- loginAndWaitForPageWithoutDateRange(DETECTIONS_URL, ROLES.soc_manager);
- waitForAlertsIndexToBeCreated();
- });
-
- beforeEach(() => {
- // Index mapping outdated is forced to return true as being outdated so that we get the
- // need admin callouts being shown.
- cy.intercept('GET', '/api/detection_engine/index', {
- index_mapping_outdated: true,
- name: '.siem-signals-default',
- });
- });
-
- context('On Detections home page', () => {
- beforeEach(() => {
- loadPageAsPlatformEngineerUser(DETECTIONS_URL);
- });
-
- it('We show the need admin primary callout', () => {
- waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
- getCallOut(ALERTS_CALLOUT).should('not.exist');
- getCallOut(RULES_CALLOUT).should('not.exist');
- });
- });
-
- context('On Rules Management page', () => {
- beforeEach(() => {
- loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
- });
-
- it('We show 1 primary callout of need admin', () => {
- waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
- getCallOut(ALERTS_CALLOUT).should('not.exist');
- getCallOut(RULES_CALLOUT).should('not.exist');
- });
- });
-
- context('On Rule Details page', () => {
- beforeEach(() => {
- createCustomRule(newRule);
- loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
- waitForPageTitleToBeShown();
- goToRuleDetails();
- });
-
- afterEach(() => {
- deleteCustomRule();
- });
-
- it('We show 1 primary callout', () => {
- waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
- getCallOut(ALERTS_CALLOUT).should('not.exist');
- getCallOut(RULES_CALLOUT).should('not.exist');
- });
- });
-});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_t1_analyst.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_t1_analyst.spec.ts
deleted file mode 100644
index b558405185f7e..0000000000000
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_t1_analyst.spec.ts
+++ /dev/null
@@ -1,85 +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
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ROLES } from '../../../common/test';
-import { DETECTIONS_RULE_MANAGEMENT_URL, DETECTIONS_URL } from '../../urls/navigation';
-import { newRule } from '../../objects/rule';
-import { PAGE_TITLE } from '../../screens/common/page';
-
-import {
- loginAndWaitForPageWithoutDateRange,
- waitForPageWithoutDateRange,
-} from '../../tasks/login';
-import { waitForAlertsIndexToBeCreated } from '../../tasks/alerts';
-import { goToRuleDetails } from '../../tasks/alerts_detection_rules';
-import { createCustomRule, deleteCustomRule } from '../../tasks/api_calls/rules';
-import { getCallOut } from '../../tasks/common/callouts';
-import { cleanKibana } from '../../tasks/common';
-
-const loadPageAsPlatformEngineerUser = (url: string) => {
- waitForPageWithoutDateRange(url, ROLES.t1_analyst);
- waitForPageTitleToBeShown();
-};
-
-const waitForPageTitleToBeShown = () => {
- cy.get(PAGE_TITLE).should('be.visible');
-};
-
-describe('Detections > Need Admin Callouts indicating an admin is needed to migrate the alert data set', () => {
- const NEED_ADMIN_FOR_UPDATE_CALLOUT = 'need-admin-for-update-rules';
- const ALERTS_CALLOUT = 'read-only-access-to-alerts';
- const RULES_CALLOUT = 'read-only-access-to-rules';
-
- before(() => {
- cleanKibana();
- loginAndWaitForPageWithoutDateRange(DETECTIONS_URL, ROLES.t1_analyst);
- waitForAlertsIndexToBeCreated();
- });
-
- context('On Detections home page', () => {
- beforeEach(() => {
- loadPageAsPlatformEngineerUser(DETECTIONS_URL);
- });
-
- it('We show no callouts', () => {
- getCallOut(ALERTS_CALLOUT).should('not.exist');
- getCallOut(RULES_CALLOUT).should('not.exist');
- getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
- });
- });
-
- context('On Rules Management page', () => {
- beforeEach(() => {
- loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
- });
-
- it('We show no callouts', () => {
- getCallOut(ALERTS_CALLOUT).should('not.exist');
- getCallOut(RULES_CALLOUT).should('not.exist');
- getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
- });
- });
-
- context('On Rule Details page', () => {
- beforeEach(() => {
- createCustomRule(newRule);
- loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
- waitForPageTitleToBeShown();
- goToRuleDetails();
- });
-
- afterEach(() => {
- deleteCustomRule();
- });
-
- it('We show no callouts', () => {
- getCallOut(ALERTS_CALLOUT).should('not.exist');
- getCallOut(RULES_CALLOUT).should('not.exist');
- getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
- });
- });
-});
diff --git a/x-pack/plugins/security_solution/cypress/tasks/common/callouts.ts b/x-pack/plugins/security_solution/cypress/tasks/common/callouts.ts
index 4139c911e4063..8440409f80f38 100644
--- a/x-pack/plugins/security_solution/cypress/tasks/common/callouts.ts
+++ b/x-pack/plugins/security_solution/cypress/tasks/common/callouts.ts
@@ -12,13 +12,11 @@ export const getCallOut = (id: string, options?: Cypress.Timeoutable) => {
};
export const waitForCallOutToBeShown = (id: string, color: string) => {
- getCallOut(id, { timeout: 10000 })
- .should('be.visible')
- .should('have.class', `euiCallOut--${color}`);
+ getCallOut(id).should('be.visible').should('have.class', `euiCallOut--${color}`);
};
export const dismissCallOut = (id: string) => {
- getCallOut(id, { timeout: 10000 }).within(() => {
+ getCallOut(id).within(() => {
cy.get(CALLOUT_DISMISS_BTN).should('be.visible').click();
cy.root().should('not.exist');
});
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/query.all_hosts.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/query.all_hosts.dsl.ts
index 08c9711794978..892801a3aed0b 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/query.all_hosts.dsl.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/query.all_hosts.dsl.ts
@@ -87,6 +87,6 @@ const getQueryOrder = (sort: SortField): QueryOrder => {
case HostsFields.hostName:
return { _key: sort.direction };
default:
- return assertUnreachable(sort.field as never);
+ return assertUnreachable(sort.field);
}
};