From 03404135874bb1ad4393bb86f200b0cd287b5554 Mon Sep 17 00:00:00 2001 From: FrankHassanabad Date: Fri, 5 Feb 2021 13:45:45 -0700 Subject: [PATCH] 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 51f4ce24cee66d..8320944f665f33 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 00000000000000..cb4658f5247779 --- /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 364320859676b4..8798249ca56829 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 83f800529a8f1a..ea31c0c24ef084 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 ( );