From 3f7704fadafd39870e8513f77502bdab644c5002 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Sat, 4 Apr 2020 07:21:27 -0700 Subject: [PATCH 1/4] Fix bug that coerced empty scaled float value to 0 (#62251) (#62537) --- .../mappings_editor/constants/parameters_definition.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx index 732449f382f93..1b9372e4b50c4 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx @@ -504,7 +504,7 @@ export const PARAMETERS_DEFINITION: { [key in ParameterName]: ParameterDefinitio fieldConfig: { defaultValue: '', type: FIELD_TYPES.NUMBER, - deserializer: (value: string | number) => +value, + deserializer: (value: string | number) => (value === '' ? value : +value), formatters: [toInt], label: i18n.translate('xpack.idxMgmt.mappingsEditor.parameters.scalingFactorLabel', { defaultMessage: 'Scaling factor', From 22cb4e78353ef536916cfcaf204f5172abbe3cb1 Mon Sep 17 00:00:00 2001 From: MadameSheema Date: Sat, 4 Apr 2020 16:50:52 +0200 Subject: [PATCH 2/4] fixes flakiness (#62406) (#62504) * fixes flakiness * updates 'number of signals' selector * changes the way we are asserting the text --- .../cypress/integration/detections.spec.ts | 77 ++++++++++--------- .../siem/cypress/screens/detections.ts | 2 +- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/x-pack/legacy/plugins/siem/cypress/integration/detections.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/detections.spec.ts index 646132c3f88eb..f38cb2285b480 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/detections.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/detections.spec.ts @@ -42,16 +42,15 @@ describe('Detections', () => { cy.get(NUMBER_OF_SIGNALS) .invoke('text') .then(numberOfSignals => { - cy.get(SHOWING_SIGNALS) - .invoke('text') - .should('eql', `Showing ${numberOfSignals} signals`); + cy.get(SHOWING_SIGNALS).should('have.text', `Showing ${numberOfSignals} signals`); const numberOfSignalsToBeClosed = 3; selectNumberOfSignals(numberOfSignalsToBeClosed); - cy.get(SELECTED_SIGNALS) - .invoke('text') - .should('eql', `Selected ${numberOfSignalsToBeClosed} signals`); + cy.get(SELECTED_SIGNALS).should( + 'have.text', + `Selected ${numberOfSignalsToBeClosed} signals` + ); closeSignals(); waitForSignals(); @@ -59,30 +58,33 @@ describe('Detections', () => { waitForSignals(); const expectedNumberOfSignalsAfterClosing = +numberOfSignals - numberOfSignalsToBeClosed; - cy.get(NUMBER_OF_SIGNALS) - .invoke('text') - .should('eq', expectedNumberOfSignalsAfterClosing.toString()); - cy.get(SHOWING_SIGNALS) - .invoke('text') - .should('eql', `Showing ${expectedNumberOfSignalsAfterClosing.toString()} signals`); + cy.get(NUMBER_OF_SIGNALS).should( + 'have.text', + expectedNumberOfSignalsAfterClosing.toString() + ); + + cy.get(SHOWING_SIGNALS).should( + 'have.text', + `Showing ${expectedNumberOfSignalsAfterClosing.toString()} signals` + ); goToClosedSignals(); waitForSignals(); - cy.get(NUMBER_OF_SIGNALS) - .invoke('text') - .should('eql', numberOfSignalsToBeClosed.toString()); - cy.get(SHOWING_SIGNALS) - .invoke('text') - .should('eql', `Showing ${numberOfSignalsToBeClosed.toString()} signals`); + cy.get(NUMBER_OF_SIGNALS).should('have.text', numberOfSignalsToBeClosed.toString()); + cy.get(SHOWING_SIGNALS).should( + 'have.text', + `Showing ${numberOfSignalsToBeClosed.toString()} signals` + ); cy.get(SIGNALS).should('have.length', numberOfSignalsToBeClosed); const numberOfSignalsToBeOpened = 1; selectNumberOfSignals(numberOfSignalsToBeOpened); - cy.get(SELECTED_SIGNALS) - .invoke('text') - .should('eql', `Selected ${numberOfSignalsToBeOpened} signal`); + cy.get(SELECTED_SIGNALS).should( + 'have.text', + `Selected ${numberOfSignalsToBeOpened} signal` + ); openSignals(); waitForSignals(); @@ -93,15 +95,14 @@ describe('Detections', () => { waitForSignals(); const expectedNumberOfClosedSignalsAfterOpened = 2; - cy.get(NUMBER_OF_SIGNALS) - .invoke('text') - .should('eql', expectedNumberOfClosedSignalsAfterOpened.toString()); - cy.get(SHOWING_SIGNALS) - .invoke('text') - .should( - 'eql', - `Showing ${expectedNumberOfClosedSignalsAfterOpened.toString()} signals` - ); + cy.get(NUMBER_OF_SIGNALS).should( + 'have.text', + expectedNumberOfClosedSignalsAfterOpened.toString() + ); + cy.get(SHOWING_SIGNALS).should( + 'have.text', + `Showing ${expectedNumberOfClosedSignalsAfterOpened.toString()} signals` + ); cy.get(SIGNALS).should('have.length', expectedNumberOfClosedSignalsAfterOpened); goToOpenedSignals(); @@ -109,13 +110,15 @@ describe('Detections', () => { const expectedNumberOfOpenedSignals = +numberOfSignals - expectedNumberOfClosedSignalsAfterOpened; - cy.get(SHOWING_SIGNALS) - .invoke('text') - .should('eql', `Showing ${expectedNumberOfOpenedSignals.toString()} signals`); - - cy.get('[data-test-subj="server-side-event-count"]') - .invoke('text') - .should('eql', expectedNumberOfOpenedSignals.toString()); + cy.get(SHOWING_SIGNALS).should( + 'have.text', + `Showing ${expectedNumberOfOpenedSignals.toString()} signals` + ); + + cy.get('[data-test-subj="server-side-event-count"]').should( + 'have.text', + expectedNumberOfOpenedSignals.toString() + ); }); }); diff --git a/x-pack/legacy/plugins/siem/cypress/screens/detections.ts b/x-pack/legacy/plugins/siem/cypress/screens/detections.ts index f388ac1215d01..cb776be8d7b6b 100644 --- a/x-pack/legacy/plugins/siem/cypress/screens/detections.ts +++ b/x-pack/legacy/plugins/siem/cypress/screens/detections.ts @@ -10,7 +10,7 @@ export const LOADING_SIGNALS_PANEL = '[data-test-subj="loading-signals-panel"]'; export const MANAGE_SIGNAL_DETECTION_RULES_BTN = '[data-test-subj="manage-signal-detection-rules"]'; -export const NUMBER_OF_SIGNALS = '[data-test-subj="server-side-event-count"]'; +export const NUMBER_OF_SIGNALS = '[data-test-subj="server-side-event-count"] .euiBadge__text'; export const OPEN_CLOSE_SIGNAL_BTN = '[data-test-subj="update-signal-status-button"]'; From 868cf864c0a3e84a07ecfe346499d4f21ece8f64 Mon Sep 17 00:00:00 2001 From: "Devin W. Hurley" Date: Sat, 4 Apr 2020 11:15:18 -0400 Subject: [PATCH 3/4] =?UTF-8?q?[7.7]=20[SIEM]=20[Detection=20Engine]=20Rem?= =?UTF-8?q?ove=20has=20manage=20api=20keys=20req=E2=80=A6=20(#62535)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Alerting no longer requires the manage_api_keys privilege, so we are removing it from the detection engine code. Fixes #62387 * removes hasManageApiKeys since alerting is using the internal user api calls, manage_api_keys privilege is no longer necessary * linting error * fixes types and removes a test for manage api keys * removes manage api key reducer and updates leftover tests * moves userHasNoPermissions repeated code into a function in helpers, adds a few test cases, updated references to new function * fix test title * remove userHasNoPermissions function and remove tests, replace with just not canUserCRUD * Revert "remove userHasNoPermissions function and remove tests, replace with just not canUserCRUD" This reverts commit 93912e7e22c41a0279ba8beb69756b9f0690c56d. Co-authored-by: Elastic Machine Co-authored-by: Elastic Machine --- .../rules/use_pre_packaged_rules.test.tsx | 31 ------------------- .../rules/use_pre_packaged_rules.tsx | 13 +------- .../detection_engine/signals/mock.ts | 1 - .../detection_engine/signals/types.ts | 1 - .../signals/use_privilege_user.test.tsx | 3 -- .../signals/use_privilege_user.tsx | 13 +------- .../components/user_info/index.tsx | 21 ------------- .../detection_engine/rules/create/index.tsx | 7 ++--- .../detection_engine/rules/details/index.tsx | 13 +++----- .../detection_engine/rules/edit/index.tsx | 13 ++++---- .../detection_engine/rules/helpers.test.tsx | 24 ++++++++++++++ .../pages/detection_engine/rules/helpers.tsx | 4 +++ .../pages/detection_engine/rules/index.tsx | 19 +++++------- 13 files changed, 51 insertions(+), 112 deletions(-) diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_pre_packaged_rules.test.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_pre_packaged_rules.test.tsx index 426a1ab9238dc..4d9e283bfb9cc 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_pre_packaged_rules.test.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_pre_packaged_rules.test.tsx @@ -22,7 +22,6 @@ describe('usePersistRule', () => { usePrePackagedRules({ canUserCRUD: null, hasIndexWrite: null, - hasManageApiKey: null, isAuthenticated: null, hasEncryptionKey: null, isSignalIndexExists: null, @@ -50,7 +49,6 @@ describe('usePersistRule', () => { usePrePackagedRules({ canUserCRUD: null, hasIndexWrite: null, - hasManageApiKey: null, isAuthenticated: null, hasEncryptionKey: null, isSignalIndexExists: null, @@ -79,7 +77,6 @@ describe('usePersistRule', () => { usePrePackagedRules({ canUserCRUD: true, hasIndexWrite: true, - hasManageApiKey: true, isAuthenticated: true, hasEncryptionKey: true, isSignalIndexExists: true, @@ -116,7 +113,6 @@ describe('usePersistRule', () => { usePrePackagedRules({ canUserCRUD: true, hasIndexWrite: true, - hasManageApiKey: true, isAuthenticated: true, hasEncryptionKey: true, isSignalIndexExists: true, @@ -139,7 +135,6 @@ describe('usePersistRule', () => { usePrePackagedRules({ canUserCRUD: false, hasIndexWrite: true, - hasManageApiKey: true, isAuthenticated: true, hasEncryptionKey: true, isSignalIndexExists: true, @@ -161,29 +156,6 @@ describe('usePersistRule', () => { usePrePackagedRules({ canUserCRUD: true, hasIndexWrite: false, - hasManageApiKey: true, - isAuthenticated: true, - hasEncryptionKey: true, - isSignalIndexExists: true, - }) - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - let resp = null; - if (result.current.createPrePackagedRules) { - resp = await result.current.createPrePackagedRules(); - } - expect(resp).toEqual(false); - }); - }); - - test('can NOT createPrePackagedRules because hasManageApiKey === false', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - usePrePackagedRules({ - canUserCRUD: true, - hasIndexWrite: true, - hasManageApiKey: false, isAuthenticated: true, hasEncryptionKey: true, isSignalIndexExists: true, @@ -205,7 +177,6 @@ describe('usePersistRule', () => { usePrePackagedRules({ canUserCRUD: true, hasIndexWrite: true, - hasManageApiKey: true, isAuthenticated: false, hasEncryptionKey: true, isSignalIndexExists: true, @@ -227,7 +198,6 @@ describe('usePersistRule', () => { usePrePackagedRules({ canUserCRUD: true, hasIndexWrite: true, - hasManageApiKey: true, isAuthenticated: true, hasEncryptionKey: false, isSignalIndexExists: true, @@ -249,7 +219,6 @@ describe('usePersistRule', () => { usePrePackagedRules({ canUserCRUD: true, hasIndexWrite: true, - hasManageApiKey: true, isAuthenticated: true, hasEncryptionKey: true, isSignalIndexExists: false, diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_pre_packaged_rules.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_pre_packaged_rules.tsx index 0dd95bea8a0b2..44d5de10e361a 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_pre_packaged_rules.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_pre_packaged_rules.tsx @@ -26,7 +26,6 @@ export interface ReturnPrePackagedRules { interface UsePrePackagedRuleProps { canUserCRUD: boolean | null; hasIndexWrite: boolean | null; - hasManageApiKey: boolean | null; isAuthenticated: boolean | null; hasEncryptionKey: boolean | null; isSignalIndexExists: boolean | null; @@ -36,7 +35,6 @@ interface UsePrePackagedRuleProps { * Hook for using to get status about pre-packaged Rules from the Detection Engine API * * @param hasIndexWrite boolean - * @param hasManageApiKey boolean * @param isAuthenticated boolean * @param hasEncryptionKey boolean * @param isSignalIndexExists boolean @@ -45,7 +43,6 @@ interface UsePrePackagedRuleProps { export const usePrePackagedRules = ({ canUserCRUD, hasIndexWrite, - hasManageApiKey, isAuthenticated, hasEncryptionKey, isSignalIndexExists, @@ -117,7 +114,6 @@ export const usePrePackagedRules = ({ if ( canUserCRUD && hasIndexWrite && - hasManageApiKey && isAuthenticated && hasEncryptionKey && isSignalIndexExists @@ -185,14 +181,7 @@ export const usePrePackagedRules = ({ isSubscribed = false; abortCtrl.abort(); }; - }, [ - canUserCRUD, - hasIndexWrite, - hasManageApiKey, - isAuthenticated, - hasEncryptionKey, - isSignalIndexExists, - ]); + }, [canUserCRUD, hasIndexWrite, isAuthenticated, hasEncryptionKey, isSignalIndexExists]); return { loading, diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/mock.ts b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/mock.ts index 37e93b1481e15..6b0c7e0078268 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/mock.ts +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/mock.ts @@ -992,7 +992,6 @@ export const mockUserPrivilege: Privilege = { monitor_watcher: true, monitor_transform: true, read_ilm: true, - manage_api_key: true, manage_security: true, manage_own_api_key: false, manage_saml: true, diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/types.ts b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/types.ts index d90f94d32001d..4e97c597546a7 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/types.ts +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/types.ts @@ -54,7 +54,6 @@ export interface Privilege { monitor_watcher: boolean; monitor_transform: boolean; read_ilm: boolean; - manage_api_key: boolean; manage_security: boolean; manage_own_api_key: boolean; manage_saml: boolean; diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_privilege_user.test.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_privilege_user.test.tsx index 2682742960442..c248223c6b81b 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_privilege_user.test.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_privilege_user.test.tsx @@ -21,7 +21,6 @@ describe('usePrivilegeUser', () => { hasEncryptionKey: null, hasIndexManage: null, hasIndexWrite: null, - hasManageApiKey: null, isAuthenticated: null, loading: true, }); @@ -39,7 +38,6 @@ describe('usePrivilegeUser', () => { hasEncryptionKey: true, hasIndexManage: true, hasIndexWrite: true, - hasManageApiKey: true, isAuthenticated: true, loading: false, }); @@ -61,7 +59,6 @@ describe('usePrivilegeUser', () => { hasEncryptionKey: false, hasIndexManage: false, hasIndexWrite: false, - hasManageApiKey: false, isAuthenticated: false, loading: false, }); diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_privilege_user.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_privilege_user.tsx index c58e62c062fae..140dd1544b12b 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_privilege_user.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_privilege_user.tsx @@ -15,7 +15,6 @@ export interface ReturnPrivilegeUser { isAuthenticated: boolean | null; hasEncryptionKey: boolean | null; hasIndexManage: boolean | null; - hasManageApiKey: boolean | null; hasIndexWrite: boolean | null; } /** @@ -27,17 +26,12 @@ export const usePrivilegeUser = (): ReturnPrivilegeUser => { const [privilegeUser, setPrivilegeUser] = useState< Pick< ReturnPrivilegeUser, - | 'isAuthenticated' - | 'hasEncryptionKey' - | 'hasIndexManage' - | 'hasManageApiKey' - | 'hasIndexWrite' + 'isAuthenticated' | 'hasEncryptionKey' | 'hasIndexManage' | 'hasIndexWrite' > >({ isAuthenticated: null, hasEncryptionKey: null, hasIndexManage: null, - hasManageApiKey: null, hasIndexWrite: null, }); const [, dispatchToaster] = useStateToaster(); @@ -65,10 +59,6 @@ export const usePrivilegeUser = (): ReturnPrivilegeUser => { privilege.index[indexName].create_doc || privilege.index[indexName].index || privilege.index[indexName].write, - hasManageApiKey: - privilege.cluster.manage_security || - privilege.cluster.manage_api_key || - privilege.cluster.manage_own_api_key, }); } } @@ -78,7 +68,6 @@ export const usePrivilegeUser = (): ReturnPrivilegeUser => { isAuthenticated: false, hasEncryptionKey: false, hasIndexManage: false, - hasManageApiKey: false, hasIndexWrite: false, }); errorToToaster({ title: i18n.PRIVILEGE_FETCH_FAILURE, error, dispatchToaster }); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/user_info/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/user_info/index.tsx index a96913f2ad541..9e45371fb6058 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/user_info/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/user_info/index.tsx @@ -15,7 +15,6 @@ export interface State { canUserCRUD: boolean | null; hasIndexManage: boolean | null; hasIndexWrite: boolean | null; - hasManageApiKey: boolean | null; isSignalIndexExists: boolean | null; isAuthenticated: boolean | null; hasEncryptionKey: boolean | null; @@ -27,7 +26,6 @@ const initialState: State = { canUserCRUD: null, hasIndexManage: null, hasIndexWrite: null, - hasManageApiKey: null, isSignalIndexExists: null, isAuthenticated: null, hasEncryptionKey: null, @@ -37,10 +35,6 @@ const initialState: State = { export type Action = | { type: 'updateLoading'; loading: boolean } - | { - type: 'updateHasManageApiKey'; - hasManageApiKey: boolean | null; - } | { type: 'updateHasIndexManage'; hasIndexManage: boolean | null; @@ -90,12 +84,6 @@ export const userInfoReducer = (state: State, action: Action): State => { hasIndexWrite: action.hasIndexWrite, }; } - case 'updateHasManageApiKey': { - return { - ...state, - hasManageApiKey: action.hasManageApiKey, - }; - } case 'updateIsSignalIndexExists': { return { ...state, @@ -151,7 +139,6 @@ export const useUserInfo = (): State => { canUserCRUD, hasIndexManage, hasIndexWrite, - hasManageApiKey, isSignalIndexExists, isAuthenticated, hasEncryptionKey, @@ -166,7 +153,6 @@ export const useUserInfo = (): State => { hasEncryptionKey: isApiEncryptionKey, hasIndexManage: hasApiIndexManage, hasIndexWrite: hasApiIndexWrite, - hasManageApiKey: hasApiManageApiKey, } = usePrivilegeUser(); const { loading: indexNameLoading, @@ -197,12 +183,6 @@ export const useUserInfo = (): State => { } }, [loading, hasIndexWrite, hasApiIndexWrite]); - useEffect(() => { - if (!loading && hasManageApiKey !== hasApiManageApiKey && hasApiManageApiKey != null) { - dispatch({ type: 'updateHasManageApiKey', hasManageApiKey: hasApiManageApiKey }); - } - }, [loading, hasManageApiKey, hasApiManageApiKey]); - useEffect(() => { if ( !loading && @@ -258,7 +238,6 @@ export const useUserInfo = (): State => { canUserCRUD, hasIndexManage, hasIndexWrite, - hasManageApiKey, signalIndexName, }; }; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx index 0335216672915..2686bb47925b6 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx @@ -24,7 +24,7 @@ import { StepScheduleRule } from '../components/step_schedule_rule'; import { StepRuleActions } from '../components/step_rule_actions'; import { DetectionEngineHeaderPage } from '../../components/detection_engine_header_page'; import * as RuleI18n from '../translations'; -import { redirectToDetections, getActionMessageParams } from '../helpers'; +import { redirectToDetections, getActionMessageParams, userHasNoPermissions } from '../helpers'; import { AboutStepRule, DefineStepRule, @@ -85,7 +85,6 @@ const CreateRulePageComponent: React.FC = () => { isAuthenticated, hasEncryptionKey, canUserCRUD, - hasManageApiKey, } = useUserInfo(); const [, dispatchToaster] = useStateToaster(); const [openAccordionId, setOpenAccordionId] = useState(RuleStep.defineRule); @@ -117,8 +116,6 @@ const CreateRulePageComponent: React.FC = () => { getActionMessageParams((stepsData.current['define-rule'].data as DefineStepRule).ruleType), [stepsData.current['define-rule'].data] ); - const userHasNoPermissions = - canUserCRUD != null && hasManageApiKey != null ? !canUserCRUD || !hasManageApiKey : false; const setStepData = useCallback( (step: RuleStep, data: unknown, isValid: boolean) => { @@ -274,7 +271,7 @@ const CreateRulePageComponent: React.FC = () => { if (redirectToDetections(isSignalIndexExists, isAuthenticated, hasEncryptionKey)) { return ; - } else if (userHasNoPermissions) { + } else if (userHasNoPermissions(canUserCRUD)) { return ; } diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx index b8e2310ef0614..cb4d88a8bb539 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx @@ -53,7 +53,7 @@ import * as detectionI18n from '../../translations'; import { ReadOnlyCallOut } from '../components/read_only_callout'; import { RuleSwitch } from '../components/rule_switch'; import { StepPanel } from '../components/step_panel'; -import { getStepsData, redirectToDetections } from '../helpers'; +import { getStepsData, redirectToDetections, userHasNoPermissions } from '../helpers'; import * as ruleI18n from '../translations'; import * as i18n from './translations'; import { GlobalTime } from '../../../../containers/global_time'; @@ -96,7 +96,6 @@ const RuleDetailsPageComponent: FC = ({ isAuthenticated, hasEncryptionKey, canUserCRUD, - hasManageApiKey, hasIndexWrite, signalIndexName, } = useUserInfo(); @@ -115,8 +114,6 @@ const RuleDetailsPageComponent: FC = ({ scheduleRuleData: null, }; const [lastSignals] = useSignalInfo({ ruleId }); - const userHasNoPermissions = - canUserCRUD != null && hasManageApiKey != null ? !canUserCRUD || !hasManageApiKey : false; const title = isLoading === true || rule === null ? : rule.name; const subTitle = useMemo( @@ -227,7 +224,7 @@ const RuleDetailsPageComponent: FC = ({ return ( <> {hasIndexWrite != null && !hasIndexWrite && } - {userHasNoPermissions && } + {userHasNoPermissions(canUserCRUD) && } {({ indicesExist, indexPattern }) => { return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( @@ -264,7 +261,7 @@ const RuleDetailsPageComponent: FC = ({ = ({ {ruleI18n.EDIT_RULE_SETTINGS} @@ -285,7 +282,7 @@ const RuleDetailsPageComponent: FC = ({ diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx index 60d6158987a1d..c42e7b902cd5c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx @@ -33,7 +33,12 @@ import { StepDefineRule } from '../components/step_define_rule'; import { StepScheduleRule } from '../components/step_schedule_rule'; import { StepRuleActions } from '../components/step_rule_actions'; import { formatRule } from '../create/helpers'; -import { getStepsData, redirectToDetections, getActionMessageParams } from '../helpers'; +import { + getStepsData, + redirectToDetections, + getActionMessageParams, + userHasNoPermissions, +} from '../helpers'; import * as ruleI18n from '../translations'; import { RuleStep, @@ -69,14 +74,10 @@ const EditRulePageComponent: FC = () => { isAuthenticated, hasEncryptionKey, canUserCRUD, - hasManageApiKey, } = useUserInfo(); const { detailName: ruleId } = useParams(); const [loading, rule] = useRule(ruleId); - const userHasNoPermissions = - canUserCRUD != null && hasManageApiKey != null ? !canUserCRUD || !hasManageApiKey : false; - const [initForm, setInitForm] = useState(false); const [myAboutRuleForm, setMyAboutRuleForm] = useState({ data: null, @@ -346,7 +347,7 @@ const EditRulePageComponent: FC = () => { if (redirectToDetections(isSignalIndexExists, isAuthenticated, hasEncryptionKey)) { return ; - } else if (userHasNoPermissions) { + } else if (userHasNoPermissions(canUserCRUD)) { return ; } diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.test.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.test.tsx index 522464d585cca..443dbd2c93a35 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.test.tsx @@ -14,6 +14,7 @@ import { getHumanizedDuration, getModifiedAboutDetailsData, determineDetailsValue, + userHasNoPermissions, } from './helpers'; import { mockRuleWithEverything, mockRule } from './all/__mocks__/mock'; import { esFilters } from '../../../../../../../../src/plugins/data/public'; @@ -337,4 +338,27 @@ describe('rule helpers', () => { expect(result).toEqual(aboutRuleDetailsData); }); }); + + describe('userHasNoPermissions', () => { + test("returns false when user's CRUD operations are null", () => { + const result: boolean = userHasNoPermissions(null); + const userHasNoPermissionsExpectedResult = false; + + expect(result).toEqual(userHasNoPermissionsExpectedResult); + }); + + test('returns true when user cannot CRUD', () => { + const result: boolean = userHasNoPermissions(false); + const userHasNoPermissionsExpectedResult = true; + + expect(result).toEqual(userHasNoPermissionsExpectedResult); + }); + + test('returns false when user can CRUD', () => { + const result: boolean = userHasNoPermissions(true); + const userHasNoPermissionsExpectedResult = false; + + expect(result).toEqual(userHasNoPermissionsExpectedResult); + }); + }); }); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx index b6afba527ccdc..db1f2298b5ea7 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx @@ -267,3 +267,7 @@ export const getActionMessageParams = memoizeOne((ruleType: RuleType | undefined ...actionMessageRuleParams.map(param => `context.rule.${param}`), ]; }); + +// typed as null not undefined as the initial state for this value is null. +export const userHasNoPermissions = (canUserCRUD: boolean | null): boolean => + canUserCRUD != null ? !canUserCRUD : false; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/index.tsx index 2b93ec8b10112..8831bc77691fa 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/index.tsx @@ -23,7 +23,7 @@ import { AllRules } from './all'; import { ImportDataModal } from '../../../components/import_data_modal'; import { ReadOnlyCallOut } from './components/read_only_callout'; import { UpdatePrePackagedRulesCallOut } from './components/pre_packaged_rules/update_callout'; -import { getPrePackagedRuleStatus, redirectToDetections } from './helpers'; +import { getPrePackagedRuleStatus, redirectToDetections, userHasNoPermissions } from './helpers'; import * as i18n from './translations'; type Func = (refreshPrePackagedRule?: boolean) => void; @@ -38,7 +38,6 @@ const RulesPageComponent: React.FC = () => { hasEncryptionKey, canUserCRUD, hasIndexWrite, - hasManageApiKey, } = useUserInfo(); const { createPrePackagedRules, @@ -52,7 +51,6 @@ const RulesPageComponent: React.FC = () => { } = usePrePackagedRules({ canUserCRUD, hasIndexWrite, - hasManageApiKey, isSignalIndexExists, isAuthenticated, hasEncryptionKey, @@ -63,9 +61,6 @@ const RulesPageComponent: React.FC = () => { rulesNotUpdated ); - const userHasNoPermissions = - canUserCRUD != null && hasManageApiKey != null ? !canUserCRUD || !hasManageApiKey : false; - const handleRefreshRules = useCallback(async () => { if (refreshRulesData.current != null) { refreshRulesData.current(true); @@ -95,7 +90,7 @@ const RulesPageComponent: React.FC = () => { return ( <> - {userHasNoPermissions && } + {userHasNoPermissions(canUserCRUD) && } setShowImportModal(false)} @@ -125,7 +120,7 @@ const RulesPageComponent: React.FC = () => { {i18n.LOAD_PREPACKAGED_RULES} @@ -138,7 +133,7 @@ const RulesPageComponent: React.FC = () => { data-test-subj="reloadPrebuiltRulesBtn" iconType="plusInCircle" isLoading={loadingCreatePrePackagedRules} - isDisabled={userHasNoPermissions || loading} + isDisabled={userHasNoPermissions(canUserCRUD) || loading} onClick={handleCreatePrePackagedRules} > {i18n.RELOAD_MISSING_PREPACKAGED_RULES(rulesNotInstalled ?? 0)} @@ -148,7 +143,7 @@ const RulesPageComponent: React.FC = () => { { setShowImportModal(true); }} @@ -162,7 +157,7 @@ const RulesPageComponent: React.FC = () => { fill href={getCreateRuleUrl()} iconType="plusInCircle" - isDisabled={userHasNoPermissions || loading} + isDisabled={userHasNoPermissions(canUserCRUD) || loading} > {i18n.ADD_NEW_RULE} @@ -180,7 +175,7 @@ const RulesPageComponent: React.FC = () => { createPrePackagedRules={createPrePackagedRules} loading={loading || prePackagedRuleLoading} loadingCreatePrePackagedRules={loadingCreatePrePackagedRules} - hasNoPermissions={userHasNoPermissions} + hasNoPermissions={userHasNoPermissions(canUserCRUD)} refetchPrePackagedRulesStatus={handleRefetchPrePackagedRulesStatus} rulesCustomInstalled={rulesCustomInstalled} rulesInstalled={rulesInstalled} From 3aea932857b473dc3d42268f4a096dddc3e284c4 Mon Sep 17 00:00:00 2001 From: Spencer Date: Sat, 4 Apr 2020 10:24:12 -0700 Subject: [PATCH 4/4] [7.7] [jenkins] refer to sizes in most pipeline code (#62082) (#62550) * [jenkins] refer to sizes in most pipeline code * switch back to `linux && immutable` for small instances Co-authored-by: spalger Co-authored-by: Elastic Machine Co-authored-by: spalger Co-authored-by: Elastic Machine --- .ci/Jenkinsfile_coverage | 2 +- .ci/Jenkinsfile_visual_baseline | 4 +-- .ci/es-snapshots/Jenkinsfile_build_es | 2 +- .ci/es-snapshots/Jenkinsfile_verify_es | 2 +- vars/workers.groovy | 35 ++++++++++++++++++-------- 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/.ci/Jenkinsfile_coverage b/.ci/Jenkinsfile_coverage index 6b8dc31bab34e..f2a58e7b6a7ac 100644 --- a/.ci/Jenkinsfile_coverage +++ b/.ci/Jenkinsfile_coverage @@ -44,7 +44,7 @@ kibanaPipeline(timeoutMinutes: 180) { 'xpack-ciGroup10': kibanaPipeline.xpackCiGroupProcess(10), ]), ]) - workers.base(name: 'coverage-worker', label: 'tests-l', ramDisk: false, bootstrapped: false) { + workers.base(name: 'coverage-worker', size: 'l', ramDisk: false, bootstrapped: false) { kibanaPipeline.downloadCoverageArtifacts() kibanaPipeline.bash( ''' diff --git a/.ci/Jenkinsfile_visual_baseline b/.ci/Jenkinsfile_visual_baseline index 5c13ccccd9c6f..815c1345bbb68 100644 --- a/.ci/Jenkinsfile_visual_baseline +++ b/.ci/Jenkinsfile_visual_baseline @@ -7,12 +7,12 @@ kibanaPipeline(timeoutMinutes: 120) { catchError { parallel([ 'oss-visualRegression': { - workers.ci(name: 'oss-visualRegression', label: 'linux && immutable', ramDisk: false) { + workers.ci(name: 'oss-visualRegression', size: 's', ramDisk: false) { kibanaPipeline.functionalTestProcess('oss-visualRegression', './test/scripts/jenkins_visual_regression.sh')(1) } }, 'xpack-visualRegression': { - workers.ci(name: 'xpack-visualRegression', label: 'linux && immutable', ramDisk: false) { + workers.ci(name: 'xpack-visualRegression', size: 's', ramDisk: false) { kibanaPipeline.functionalTestProcess('xpack-visualRegression', './test/scripts/jenkins_xpack_visual_regression.sh')(1) } }, diff --git a/.ci/es-snapshots/Jenkinsfile_build_es b/.ci/es-snapshots/Jenkinsfile_build_es index a00bcb3bbc946..a3470cd750738 100644 --- a/.ci/es-snapshots/Jenkinsfile_build_es +++ b/.ci/es-snapshots/Jenkinsfile_build_es @@ -25,7 +25,7 @@ def PROMOTE_WITHOUT_VERIFY = !!params.PROMOTE_WITHOUT_VERIFICATION timeout(time: 120, unit: 'MINUTES') { timestamps { ansiColor('xterm') { - node('linux && immutable') { + node(workers.label('s')) { catchErrors { def VERSION def SNAPSHOT_ID diff --git a/.ci/es-snapshots/Jenkinsfile_verify_es b/.ci/es-snapshots/Jenkinsfile_verify_es index ce472a404c053..ade79f27e10e9 100644 --- a/.ci/es-snapshots/Jenkinsfile_verify_es +++ b/.ci/es-snapshots/Jenkinsfile_verify_es @@ -61,7 +61,7 @@ kibanaPipeline(timeoutMinutes: 120) { } def promoteSnapshot(snapshotVersion, snapshotId) { - node('linux && immutable') { + node(workers.label('s')) { esSnapshots.promote(snapshotVersion, snapshotId) } } diff --git a/vars/workers.groovy b/vars/workers.groovy index c5638f2624fe5..1c55c676d9425 100644 --- a/vars/workers.groovy +++ b/vars/workers.groovy @@ -1,23 +1,38 @@ // "Workers" in this file will spin up an instance, do some setup etc depending on the configuration, and then execute some work that you define // e.g. workers.base(name: 'my-worker') { sh "echo 'ready to execute some kibana scripts'" } +def label(size) { + switch(size) { + case 's': + return 'linux && immutable' + case 'l': + return 'tests-l' + case 'xl': + return 'tests-xl' + case 'xxl': + return 'tests-xxl' + } + + error "unknown size '${size}'" +} + /* The base worker that all of the others use. Will clone the scm (assumed to be kibana), and run kibana bootstrap processes by default. Parameters: - label - gobld/agent label to use, e.g. 'linux && immutable' + size - size of worker label to use, e.g. 's' or 'xl' ramDisk - Should the workspace be mounted in memory? Default: true bootstrapped - If true, download kibana dependencies, run kbn bootstrap, etc. Default: true name - Name of the worker for display purposes, filenames, etc. scm - Jenkins scm configuration for checking out code. Use `null` to disable checkout. Default: inherited from job */ def base(Map params, Closure closure) { - def config = [label: '', ramDisk: true, bootstrapped: true, name: 'unnamed-worker', scm: scm] + params - if (!config.label) { - error "You must specify an agent label, such as 'tests-xl' or 'linux && immutable', when using workers.base()" + def config = [size: '', ramDisk: true, bootstrapped: true, name: 'unnamed-worker', scm: scm] + params + if (!config.size) { + error "You must specify an agent size, such as 'xl' or 's', when using workers.base()" } - node(config.label) { + node(label(config.size)) { agentInfo.print() if (config.ramDisk) { @@ -88,7 +103,7 @@ def ci(Map params, Closure closure) { // Worker for running the current intake jobs. Just runs a single script after bootstrap. def intake(jobName, String script) { return { - ci(name: jobName, label: 'linux && immutable', ramDisk: false) { + ci(name: jobName, size: 's', ramDisk: false) { withEnv(["JOB=${jobName}"]) { runbld(script, "Execute ${jobName}") } @@ -99,7 +114,7 @@ def intake(jobName, String script) { // Worker for running functional tests. Runs a setup process (e.g. the kibana build) then executes a map of closures in parallel (e.g. one for each ciGroup) def functional(name, Closure setup, Map processes) { return { - parallelProcesses(name: name, setup: setup, processes: processes, delayBetweenProcesses: 20, label: 'tests-xl') + parallelProcesses(name: name, setup: setup, processes: processes, delayBetweenProcesses: 20, size: 'xl') } } @@ -111,12 +126,12 @@ def functional(name, Closure setup, Map processes) { setup: Closure to execute after the agent is bootstrapped, before starting the parallel work processes: Map of closures that will execute in parallel after setup. Each closure is passed a unique number. delayBetweenProcesses: Number of seconds to wait between starting the parallel processes. Useful to spread the load of heavy init processes, e.g. Elasticsearch starting up. Default: 0 - label: gobld/agent label to use, e.g. 'linux && immutable'. Default: 'tests-xl', a 32 CPU machine used for running many functional test suites in parallel + size: size of worker label to use, e.g. 's' or 'xl' */ def parallelProcesses(Map params) { - def config = [name: 'parallel-worker', setup: {}, processes: [:], delayBetweenProcesses: 0, label: 'tests-xl'] + params + def config = [name: 'parallel-worker', setup: {}, processes: [:], delayBetweenProcesses: 0, size: 'xl'] + params - ci(label: config.label, name: config.name) { + ci(size: config.size, name: config.name) { config.setup() def nextProcessNumber = 1