Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SIEM][Detections] Restrict ML rule modification to ML Admins #65583

Merged
merged 27 commits into from
May 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3317cb3
Move common ML types and functions into siem/common
rylnd May 6, 2020
870d914
Use ML's Capabilities type in lieu of our own
rylnd May 6, 2020
d0bbd60
Add authorization helpers for ML
rylnd May 6, 2020
9279c7a
Use mlAuthz on our import rule route
rylnd May 6, 2020
1eccb01
Add mlAuthz checks to remaining rule routes
rylnd May 6, 2020
7f98838
Remove validateLicenseForRuleType
rylnd May 6, 2020
2f39bac
Fix failing tests
rylnd May 6, 2020
1eb1947
Merge branch 'master' into ml_rules_ml_admins
rylnd May 6, 2020
8ebf209
Cleanup: fixing type errors
rylnd May 6, 2020
c01f1cf
Merge branch 'master' into ml_rules_ml_admins
rylnd May 7, 2020
973ddec
Clean up some types from ML
rylnd May 7, 2020
9f5791c
Refactor mlAuthz to defer authz validation until validator is called
rylnd May 7, 2020
f900d55
Cache validation promise
rylnd May 7, 2020
9f4bcdc
Make our result caching more explicit
rylnd May 8, 2020
647624d
Add additional unit tests around some edge cases
rylnd May 8, 2020
aab4af7
Remove redundant test setup
rylnd May 8, 2020
6ed03b8
Empty messages are invalid
rylnd May 8, 2020
baa67db
Fix validity logic
rylnd May 8, 2020
a49048b
Merge branch 'master' into ml_rules_ml_admins
rylnd May 8, 2020
e51c8dd
Prevent patching of ML rules by non-ML admins
rylnd May 8, 2020
0e085bc
Fix our update_prepackaged_rules route
rylnd May 8, 2020
97ecba9
Fix update_prepackaged_rules tests
rylnd May 8, 2020
9d8ef0c
Remove id and ruleId from patchRules parameters
rylnd May 8, 2020
040b5c3
Merge branch 'master' into ml_rules_ml_admins
elasticmachine May 9, 2020
4a827db
Merge branch 'master' into ml_rules_ml_admins
elasticmachine May 11, 2020
553234e
Merge branch 'master' into ml_rules_ml_admins
elasticmachine May 11, 2020
9b5e47b
Merge branch 'master' into ml_rules_ml_admins
elasticmachine May 11, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { MlCapabilities } from './types';
import { MlCapabilitiesResponse } from '../../../ml/common/types/capabilities';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice they have types we can use 👍 !


export const emptyMlCapabilities: MlCapabilities = {
export const emptyMlCapabilities: MlCapabilitiesResponse = {
capabilities: {
canAccessML: false,
canGetAnnotations: false,
canCreateAnnotation: false,
canDeleteAnnotation: false,
canGetJobs: false,
canCreateJob: false,
canDeleteJob: false,
Expand All @@ -26,11 +30,8 @@ export const emptyMlCapabilities: MlCapabilities = {
canCreateFilter: false,
canDeleteFilter: false,
canFindFileStructure: false,
canGetDataFrame: false,
canDeleteDataFrame: false,
canPreviewDataFrame: false,
canCreateDataFrame: false,
canStartStopDataFrame: false,
canCreateDatafeed: false,
canDeleteDatafeed: false,
canGetDataFrameAnalytics: false,
canDeleteDataFrameAnalytics: false,
canCreateDataFrameAnalytics: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { hasMlAdminPermissions } from './has_ml_admin_permissions';
import { cloneDeep } from 'lodash/fp';
import { emptyMlCapabilities } from '../empty_ml_capabilities';
import { emptyMlCapabilities } from './empty_ml_capabilities';

describe('has_ml_admin_permissions', () => {
let mlCapabilities = cloneDeep(emptyMlCapabilities);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { MlCapabilities } from '../types';
import { MlCapabilitiesResponse } from '../../../ml/common/types/capabilities';

export const hasMlAdminPermissions = (capabilities: MlCapabilities): boolean =>
export const hasMlAdminPermissions = (capabilities: MlCapabilitiesResponse): boolean =>
getDataFeedPermissions(capabilities) &&
getJobPermissions(capabilities) &&
getFilterPermissions(capabilities) &&
getCalendarPermissions(capabilities);

const getDataFeedPermissions = ({ capabilities }: MlCapabilities): boolean =>
const getDataFeedPermissions = ({ capabilities }: MlCapabilitiesResponse): boolean =>
capabilities.canGetDatafeeds &&
capabilities.canStartStopDatafeed &&
capabilities.canUpdateDatafeed &&
capabilities.canPreviewDatafeed;

const getJobPermissions = ({ capabilities }: MlCapabilities): boolean =>
const getJobPermissions = ({ capabilities }: MlCapabilitiesResponse): boolean =>
capabilities.canCreateJob &&
capabilities.canGetJobs &&
capabilities.canUpdateJob &&
Expand All @@ -27,8 +27,8 @@ const getJobPermissions = ({ capabilities }: MlCapabilities): boolean =>
capabilities.canCloseJob &&
capabilities.canForecastJob;

const getFilterPermissions = ({ capabilities }: MlCapabilities) =>
const getFilterPermissions = ({ capabilities }: MlCapabilitiesResponse) =>
capabilities.canGetFilters && capabilities.canCreateFilter && capabilities.canDeleteFilter;

const getCalendarPermissions = ({ capabilities }: MlCapabilities) =>
const getCalendarPermissions = ({ capabilities }: MlCapabilitiesResponse) =>
capabilities.canCreateCalendar && capabilities.canGetCalendars && capabilities.canDeleteCalendar;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { cloneDeep } from 'lodash/fp';
import { hasMlUserPermissions } from './has_ml_user_permissions';
import { emptyMlCapabilities } from '../empty_ml_capabilities';
import { emptyMlCapabilities } from './empty_ml_capabilities';

describe('has_ml_user_permissions', () => {
let mlCapabilities = cloneDeep(emptyMlCapabilities);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { MlCapabilities } from '../types';
import { MlCapabilitiesResponse } from '../../../ml/common/types/capabilities';

export const hasMlUserPermissions = (capabilities: MlCapabilities): boolean =>
export const hasMlUserPermissions = (capabilities: MlCapabilitiesResponse): boolean =>
capabilities.capabilities.canGetJobs &&
capabilities.capabilities.canGetDatafeeds &&
capabilities.capabilities.canGetCalendars;
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { isJobStarted, isJobLoading, isJobFailed } from './ml_helpers';
import { isJobStarted, isJobLoading, isJobFailed } from './helpers';

describe('isJobStarted', () => {
test('returns false if only jobState is enabled', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { RuleType } from './types';
import { RuleType } from '../detection_engine/types';

// Based on ML Job/Datafeed States from x-pack/legacy/plugins/ml/common/constants/states.js
const enabledStates = ['started', 'opened'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useState, useEffect } from 'react';
import { DEFAULT_ANOMALY_SCORE } from '../../../../common/constants';
import { anomaliesTableData } from '../api/anomalies_table_data';
import { InfluencerInput, Anomalies, CriteriaFields } from '../types';
import { hasMlUserPermissions } from '../permissions/has_ml_user_permissions';
import { hasMlUserPermissions } from '../../../../common/machine_learning/has_ml_user_permissions';
import { useSiemJobs } from '../../ml_popover/hooks/use_siem_jobs';
import { useMlCapabilities } from '../../ml_popover/hooks/use_ml_capabilities';
import { useStateToaster, errorToToaster } from '../../toasters';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { InfluencerInput, MlCapabilities } from '../types';
import { MlCapabilitiesResponse } from '../../../../../ml/public';
import { KibanaServices } from '../../../lib/kibana';
import { InfluencerInput } from '../types';

export interface Body {
jobIds: string[];
Expand All @@ -20,8 +21,8 @@ export interface Body {
maxExamples: number;
}

export const getMlCapabilities = async (signal: AbortSignal): Promise<MlCapabilities> => {
return KibanaServices.get().http.fetch<MlCapabilities>('/api/ml/ml_capabilities', {
export const getMlCapabilities = async (signal: AbortSignal): Promise<MlCapabilitiesResponse> => {
return KibanaServices.get().http.fetch<MlCapabilitiesResponse>('/api/ml/ml_capabilities', {
method: 'GET',
asSystemRequest: true,
signal,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@

import React, { useState, useEffect } from 'react';

import { MlCapabilities } from '../types';
import { MlCapabilitiesResponse } from '../../../../../ml/public';
import { emptyMlCapabilities } from '../../../../common/machine_learning/empty_ml_capabilities';
import { getMlCapabilities } from '../api/get_ml_capabilities';
import { emptyMlCapabilities } from '../empty_ml_capabilities';
import { errorToToaster, useStateToaster } from '../../toasters';

import * as i18n from './translations';

interface MlCapabilitiesProvider extends MlCapabilities {
interface MlCapabilitiesProvider extends MlCapabilitiesResponse {
capabilitiesFetched: boolean;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import React from 'react';
import { useAnomaliesTableData } from '../anomaly/use_anomalies_table_data';
import { HeaderSection } from '../../header_section';

import { hasMlUserPermissions } from '../../../../common/machine_learning/has_ml_user_permissions';
import * as i18n from './translations';
import { getAnomaliesHostTableColumnsCurated } from './get_anomalies_host_table_columns';
import { convertAnomaliesToHosts } from './convert_anomalies_to_hosts';
import { Loader } from '../../loader';
import { getIntervalFromAnomalies } from '../anomaly/get_interval_from_anomalies';
import { AnomaliesHostTableProps } from '../types';
import { hasMlUserPermissions } from '../permissions/has_ml_user_permissions';
import { useMlCapabilities } from '../../ml_popover/hooks/use_ml_capabilities';
import { BasicTable } from './basic_table';
import { hostEquality } from './host_equality';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import React from 'react';
import { useAnomaliesTableData } from '../anomaly/use_anomalies_table_data';
import { HeaderSection } from '../../header_section';

import { hasMlUserPermissions } from '../../../../common/machine_learning/has_ml_user_permissions';
import * as i18n from './translations';
import { convertAnomaliesToNetwork } from './convert_anomalies_to_network';
import { Loader } from '../../loader';
import { AnomaliesNetworkTableProps } from '../types';
import { getAnomaliesNetworkTableColumnsCurated } from './get_anomalies_network_table_columns';
import { useMlCapabilities } from '../../ml_popover/hooks/use_ml_capabilities';
import { hasMlUserPermissions } from '../permissions/has_ml_user_permissions';
import { BasicTable } from './basic_table';
import { networkEquality } from './network_equality';
import { getCriteriaFromNetworkType } from '../criteria/get_criteria_from_network_type';
Expand Down
47 changes: 2 additions & 45 deletions x-pack/plugins/siem/public/components/ml/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { Influencer } from '../../../../ml/public';

import { HostsType } from '../../store/hosts/model';
import { NetworkType } from '../../store/network/model';
import { FlowTarget } from '../../graphql/types';

export interface Influencer {
influencer_field_name: string;
influencer_field_values: string[];
}

export interface Source {
job_id: string;
result_type: string;
Expand All @@ -35,11 +32,6 @@ export interface Source {
influencers: Influencer[];
}

export interface Influencer {
influencer_field_name: string;
influencer_field_values: string[];
}

export interface CriteriaFields {
fieldName: string;
fieldValue: string;
Expand Down Expand Up @@ -100,41 +92,6 @@ export type AnomaliesNetworkTableProps = HostOrNetworkProps & {
flowTarget?: FlowTarget;
};

export interface MlCapabilities {
capabilities: {
canGetJobs: boolean;
canCreateJob: boolean;
canDeleteJob: boolean;
canOpenJob: boolean;
canCloseJob: boolean;
canForecastJob: boolean;
canGetDatafeeds: boolean;
canStartStopDatafeed: boolean;
canUpdateJob: boolean;
canUpdateDatafeed: boolean;
canPreviewDatafeed: boolean;
canGetCalendars: boolean;
canCreateCalendar: boolean;
canDeleteCalendar: boolean;
canGetFilters: boolean;
canCreateFilter: boolean;
canDeleteFilter: boolean;
canFindFileStructure: boolean;
canGetDataFrame: boolean;
canDeleteDataFrame: boolean;
canPreviewDataFrame: boolean;
canCreateDataFrame: boolean;
canStartStopDataFrame: boolean;
canGetDataFrameAnalytics: boolean;
canDeleteDataFrameAnalytics: boolean;
canCreateDataFrameAnalytics: boolean;
canStartStopDataFrameAnalytics: boolean;
};
isPlatinumOrTrialLicense: boolean;
mlFeatureEnabledInSpace: boolean;
upgradeInProgress: boolean;
}

const sourceOrDestination = ['source.ip', 'destination.ip'];

export const isDestinationOrSource = (value: string | null): value is DestinationOrSource =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@
import { mockSiemJobs } from './__mocks__/api';
import { filterJobs, getStablePatternTitles, searchFilter } from './helpers';

jest.mock('../ml/permissions/has_ml_admin_permissions', () => ({
hasMlAdminPermissions: () => true,
}));

describe('helpers', () => {
describe('filterJobs', () => {
test('returns all jobs when no filter is suplied', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useEffect, useState } from 'react';
import { DEFAULT_INDEX_KEY } from '../../../../common/constants';
import { checkRecognizer, getJobsSummary, getModules } from '../api';
import { SiemJob } from '../types';
import { hasMlUserPermissions } from '../../ml/permissions/has_ml_user_permissions';
import { hasMlUserPermissions } from '../../../../common/machine_learning/has_ml_user_permissions';
import { errorToToaster, useStateToaster } from '../../toasters';
import { useUiSetting$ } from '../../../lib/kibana';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
isJobLoading,
isJobFailed,
isJobStarted,
} from '../../../../common/detection_engine/ml_helpers';
} from '../../../../common/machine_learning/helpers';
import { SiemJob } from '../types';

const StaticSwitch = styled(EuiSwitch)`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ import { MlPopover } from './ml_popover';

jest.mock('../../lib/kibana');

jest.mock('../ml/permissions/has_ml_admin_permissions', () => ({
hasMlAdminPermissions: () => true,
}));

describe('MlPopover', () => {
test('shows upgrade popover on mouse click', () => {
const wrapper = mountWithIntl(<MlPopover />);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import styled from 'styled-components';

import { useKibana } from '../../lib/kibana';
import { METRIC_TYPE, TELEMETRY_EVENT, track } from '../../lib/telemetry';
import { hasMlAdminPermissions } from '../ml/permissions/has_ml_admin_permissions';
import { hasMlAdminPermissions } from '../../../common/machine_learning/has_ml_admin_permissions';
import { errorToToaster, useStateToaster, ActionToaster } from '../toasters';
import { setupMlJob, startDatafeeds, stopDatafeeds } from './api';
import { filterJobs } from './helpers';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { InspectButton, InspectButtonContainer } from '../../../inspect';
import { HostItem } from '../../../../graphql/types';
import { Loader } from '../../../loader';
import { IPDetailsLink } from '../../../links';
import { hasMlUserPermissions } from '../../../ml/permissions/has_ml_user_permissions';
import { hasMlUserPermissions } from '../../../../../common/machine_learning/has_ml_user_permissions';
import { useMlCapabilities } from '../../../ml_popover/hooks/use_ml_capabilities';
import { AnomalyScores } from '../../../ml/score/anomaly_scores';
import { Anomalies, NarrowDateRange } from '../../../ml/types';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { Loader } from '../../../loader';
import { Anomalies, NarrowDateRange } from '../../../ml/types';
import { AnomalyScores } from '../../../ml/score/anomaly_scores';
import { useMlCapabilities } from '../../../ml_popover/hooks/use_ml_capabilities';
import { hasMlUserPermissions } from '../../../ml/permissions/has_ml_user_permissions';
import { hasMlUserPermissions } from '../../../../../common/machine_learning/has_ml_user_permissions';
import { InspectButton, InspectButtonContainer } from '../../../inspect';

interface OwnProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { FormattedRelative } from '@kbn/i18n/react';
import * as H from 'history';
import React, { Dispatch } from 'react';

import { isMlRule } from '../../../../../common/detection_engine/ml_helpers';
import { isMlRule } from '../../../../../common/machine_learning/helpers';
import { Rule, RuleStatus } from '../../../../containers/detection_engine/rules';
import { getEmptyTagValue } from '../../../../components/empty_value';
import { FormattedDate } from '../../../../components/formatted_date';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import { showRulesTable } from './helpers';
import { allRulesReducer, State } from './reducer';
import { RulesTableFilters } from './rules_table_filters/rules_table_filters';
import { useMlCapabilities } from '../../../../components/ml_popover/hooks/use_ml_capabilities';
import { hasMlAdminPermissions } from '../../../../components/ml/permissions/has_ml_admin_permissions';
import { hasMlAdminPermissions } from '../../../../../common/machine_learning/has_ml_admin_permissions';

const SORT_FIELD = 'enabled';
const initialState: State = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import React from 'react';
import styled from 'styled-components';
import { EuiBadge, EuiIcon, EuiLink, EuiToolTip } from '@elastic/eui';

import { isJobStarted } from '../../../../../../common/detection_engine/ml_helpers';
import { isJobStarted } from '../../../../../../common/machine_learning/helpers';
import { useKibana } from '../../../../../lib/kibana';
import { SiemJob } from '../../../../../components/ml_popover/types';
import { ListItems } from './types';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
} from '@elastic/eui';

import styled from 'styled-components';
import { isJobStarted } from '../../../../../../common/detection_engine/ml_helpers';
import { isJobStarted } from '../../../../../../common/machine_learning/helpers';
import { FieldHook, getFieldValidityAndErrorMessage } from '../../../../../shared_imports';
import { useSiemJobs } from '../../../../../components/ml_popover/hooks/use_siem_jobs';
import { useKibana } from '../../../../../lib/kibana';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
EuiText,
} from '@elastic/eui';

import { isMlRule } from '../../../../../../common/detection_engine/ml_helpers';
import { isMlRule } from '../../../../../../common/machine_learning/helpers';
import { RuleType } from '../../../../../../common/detection_engine/types';
import { FieldHook } from '../../../../../shared_imports';
import { useKibana } from '../../../../../lib/kibana';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import styled from 'styled-components';
import deepEqual from 'fast-deep-equal';

import { DEFAULT_INDEX_KEY } from '../../../../../../common/constants';
import { isMlRule } from '../../../../../../common/detection_engine/ml_helpers';
import { isMlRule } from '../../../../../../common/machine_learning/helpers';
import { IIndexPattern } from '../../../../../../../../../src/plugins/data/public';
import { useFetchIndexPatterns } from '../../../../../containers/detection_engine/rules';
import { DEFAULT_TIMELINE_TITLE } from '../../../../../components/timeline/translations';
Expand Down Expand Up @@ -38,7 +38,7 @@ import {
import { schema } from './schema';
import * as i18n from './translations';
import { filterRuleFieldsForType, RuleFields } from '../../create/helpers';
import { hasMlAdminPermissions } from '../../../../../components/ml/permissions/has_ml_admin_permissions';
import { hasMlAdminPermissions } from '../../../../../../common/machine_learning/has_ml_admin_permissions';

const CommonUseField = getUseField({ component: Field });

Expand Down
Loading