mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[AI4DSOC] Add possibility to disable Stack Rules, Rules Settings and Maintenance window based on Serverless Tier (#214586)
This commit is contained in:
parent
caa9b3ff45
commit
6356f2cdf1
31 changed files with 636 additions and 193 deletions
|
@ -136,6 +136,7 @@ enabled:
|
|||
- x-pack/test/alerting_api_integration/security_and_spaces/group3/config.ts
|
||||
- x-pack/test/alerting_api_integration/security_and_spaces/group4/config.ts
|
||||
- x-pack/test/alerting_api_integration/security_and_spaces/group5/config.ts
|
||||
- x-pack/test/alerting_api_integration/security_and_spaces/group6/config.ts
|
||||
- x-pack/test/alerting_api_integration/security_and_spaces/group3/config_with_schedule_circuit_breaker.ts
|
||||
- x-pack/test/alerting_api_integration/security_and_spaces/group2/config_non_dedicated_task_runner.ts
|
||||
- x-pack/test/alerting_api_integration/security_and_spaces/group4/config_non_dedicated_task_runner.ts
|
||||
|
|
|
@ -5,6 +5,11 @@ xpack.osquery.enabled: false
|
|||
xpack.ml.ad.enabled: false
|
||||
xpack.ml.dfa.enabled: false
|
||||
|
||||
## Disable plugin features
|
||||
xpack.alerting.maintenanceWindow.enabled: false
|
||||
xpack.alerting.rulesSettings.enabled: false
|
||||
xpack.trigger_actions_ui.rules.enabled: false
|
||||
|
||||
xpack.features.overrides:
|
||||
### The following features are Security features hidden in Role management UI for this specific tier.
|
||||
securitySolutionTimeline.hidden: true
|
||||
|
|
|
@ -52,8 +52,8 @@ export function MaintenanceWindowCallout({
|
|||
} = kibanaServices;
|
||||
|
||||
const isMaintenanceWindowDisabled =
|
||||
!capabilities[MAINTENANCE_WINDOW_FEATURE_ID].show &&
|
||||
!capabilities[MAINTENANCE_WINDOW_FEATURE_ID].save;
|
||||
!capabilities[MAINTENANCE_WINDOW_FEATURE_ID]?.show &&
|
||||
!capabilities[MAINTENANCE_WINDOW_FEATURE_ID]?.save;
|
||||
const { data: activeMaintenanceWindows = [] } = useFetchActiveMaintenanceWindows(kibanaServices, {
|
||||
enabled: !isMaintenanceWindowDisabled,
|
||||
});
|
||||
|
|
|
@ -349,8 +349,11 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
|
|||
'xpack.stack_connectors.enableExperimental (array?)',
|
||||
'xpack.trigger_actions_ui.enableExperimental (array?)',
|
||||
'xpack.trigger_actions_ui.enableGeoTrackingThresholdAlert (boolean?)',
|
||||
'xpack.trigger_actions_ui.rules.enabled (boolean?)',
|
||||
'xpack.timelines.enableExperimental (array?)',
|
||||
'xpack.alerting.rules.run.alerts.max (number?)',
|
||||
'xpack.alerting.maintenanceWindow.enabled (boolean?)',
|
||||
'xpack.alerting.rulesSettings.enabled (boolean?)',
|
||||
'xpack.upgrade_assistant.featureSet.migrateSystemIndices (boolean?)',
|
||||
'xpack.upgrade_assistant.featureSet.mlSnapshots (boolean?)',
|
||||
'xpack.upgrade_assistant.featureSet.reindexCorrectiveActions (boolean?)',
|
||||
|
|
|
@ -255,4 +255,3 @@ export const DELETE_MAINTENANCE_WINDOW_API_PATH = `${BASE_MAINTENANCE_WINDOW_API
|
|||
|
||||
export const ALERTING_FEATURE_ID = 'alerts';
|
||||
export const MONITORING_HISTORY_LIMIT = 200;
|
||||
export const ENABLE_MAINTENANCE_WINDOWS = true;
|
||||
|
|
|
@ -68,8 +68,8 @@ export const MaintenanceWindowsPage = React.memo(() => {
|
|||
}, [navigateToCreateMaintenanceWindow]);
|
||||
|
||||
const refreshData = useCallback(() => refetch(), [refetch]);
|
||||
const showWindowMaintenance = capabilities[MAINTENANCE_WINDOW_FEATURE_ID].show;
|
||||
const writeWindowMaintenance = capabilities[MAINTENANCE_WINDOW_FEATURE_ID].save;
|
||||
const showWindowMaintenance = capabilities[MAINTENANCE_WINDOW_FEATURE_ID]?.show;
|
||||
const writeWindowMaintenance = capabilities[MAINTENANCE_WINDOW_FEATURE_ID]?.save;
|
||||
const isNotFiltered = search === '' && selectedStatus.length === 0;
|
||||
|
||||
const showEmptyPrompt =
|
||||
|
|
|
@ -26,6 +26,9 @@ const mockAlertingUIConfig: AlertingUIConfig = {
|
|||
},
|
||||
},
|
||||
},
|
||||
maintenanceWindow: {
|
||||
enabled: true,
|
||||
},
|
||||
};
|
||||
|
||||
const mockInitializerContext = coreMock.createPluginInitializerContext(mockAlertingUIConfig);
|
||||
|
|
|
@ -17,8 +17,8 @@ import type { ServerlessPluginStart } from '@kbn/serverless/public';
|
|||
import type { AlertNavigationHandler } from './alert_navigation_registry';
|
||||
import { AlertNavigationRegistry } from './alert_navigation_registry';
|
||||
import { loadRule, loadRuleType } from './services/rule_api';
|
||||
import { MAINTENANCE_WINDOWS_APP_ID } from '../common';
|
||||
import type { Rule } from '../common';
|
||||
import { ENABLE_MAINTENANCE_WINDOWS, MAINTENANCE_WINDOWS_APP_ID } from '../common';
|
||||
|
||||
export interface PluginSetupContract {
|
||||
/**
|
||||
|
@ -82,6 +82,7 @@ export interface AlertingUIConfig {
|
|||
};
|
||||
};
|
||||
};
|
||||
maintenanceWindow: { enabled: boolean };
|
||||
}
|
||||
|
||||
export class AlertingPublicPlugin
|
||||
|
@ -115,7 +116,7 @@ export class AlertingPublicPlugin
|
|||
handler: AlertNavigationHandler
|
||||
) => this.alertNavigationRegistry!.registerDefault(applicationId, handler);
|
||||
|
||||
if (ENABLE_MAINTENANCE_WINDOWS) {
|
||||
if (this.config.maintenanceWindow?.enabled) {
|
||||
plugins.management.sections.section.insightsAndAlerting.registerApp({
|
||||
id: MAINTENANCE_WINDOWS_APP_ID,
|
||||
title: i18n.translate('xpack.alerting.management.section.title', {
|
||||
|
|
|
@ -21,6 +21,9 @@ describe('config validation', () => {
|
|||
"interval": "5m",
|
||||
"removalDelay": "1h",
|
||||
},
|
||||
"maintenanceWindow": Object {
|
||||
"enabled": true,
|
||||
},
|
||||
"rules": Object {
|
||||
"maxScheduledPerMinute": 32000,
|
||||
"minimumScheduleInterval": Object {
|
||||
|
@ -38,6 +41,7 @@ describe('config validation', () => {
|
|||
},
|
||||
"rulesSettings": Object {
|
||||
"cacheInterval": 60000,
|
||||
"enabled": true,
|
||||
},
|
||||
}
|
||||
`);
|
||||
|
|
|
@ -74,8 +74,12 @@ export const configSchema = schema.object({
|
|||
cancelAlertsOnRuleTimeout: schema.boolean({ defaultValue: true }),
|
||||
rules: rulesSchema,
|
||||
rulesSettings: schema.object({
|
||||
enabled: schema.boolean({ defaultValue: true }),
|
||||
cacheInterval: schema.number({ defaultValue: DEFAULT_CACHE_INTERVAL_MS }),
|
||||
}),
|
||||
maintenanceWindow: schema.object({
|
||||
enabled: schema.boolean({ defaultValue: true }),
|
||||
}),
|
||||
});
|
||||
|
||||
export type AlertingConfig = TypeOf<typeof configSchema>;
|
||||
|
|
|
@ -83,6 +83,8 @@ export const config: PluginConfigDescriptor<AlertingConfig> = {
|
|||
schema: configSchema,
|
||||
exposeToBrowser: {
|
||||
rules: { run: { alerts: { max: true } } },
|
||||
rulesSettings: { enabled: true },
|
||||
maintenanceWindow: { enabled: true },
|
||||
},
|
||||
deprecations: ({ renameFromRoot, deprecate }) => [
|
||||
deprecate('maxEphemeralActionsPerAlert', '9.0.0', {
|
||||
|
|
|
@ -274,9 +274,12 @@ export class AlertingPlugin {
|
|||
};
|
||||
});
|
||||
|
||||
plugins.features.registerKibanaFeature(getRulesSettingsFeature(this.isServerless));
|
||||
|
||||
plugins.features.registerKibanaFeature(maintenanceWindowFeature);
|
||||
if (this.config.rulesSettings.enabled) {
|
||||
plugins.features.registerKibanaFeature(getRulesSettingsFeature(this.isServerless));
|
||||
}
|
||||
if (this.config.maintenanceWindow.enabled) {
|
||||
plugins.features.registerKibanaFeature(maintenanceWindowFeature);
|
||||
}
|
||||
|
||||
this.isESOCanEncrypt = plugins.encryptedSavedObjects.canEncrypt;
|
||||
|
||||
|
@ -405,6 +408,7 @@ export class AlertingPlugin {
|
|||
config$: plugins.unifiedSearch.autocomplete.getInitializerContextConfig().create(),
|
||||
isServerless: this.isServerless,
|
||||
docLinks: core.docLinks,
|
||||
alertingConfig: this.config,
|
||||
});
|
||||
|
||||
return {
|
||||
|
|
|
@ -10,6 +10,7 @@ import type { UsageCounter } from '@kbn/usage-collection-plugin/server';
|
|||
import type { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server';
|
||||
import type { ConfigSchema } from '@kbn/unified-search-plugin/server/config';
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { AlertingConfig } from '../config';
|
||||
import type { GetAlertIndicesAlias, ILicenseState } from '../lib';
|
||||
import type { AlertingRequestHandlerContext } from '../types';
|
||||
import { createRuleRoute } from './rule/apis/create';
|
||||
|
@ -96,6 +97,7 @@ export interface RouteOptions {
|
|||
config$?: Observable<ConfigSchema>;
|
||||
isServerless?: boolean;
|
||||
docLinks: DocLinksServiceSetup;
|
||||
alertingConfig: AlertingConfig;
|
||||
}
|
||||
|
||||
export function defineRoutes(opts: RouteOptions) {
|
||||
|
@ -106,6 +108,7 @@ export function defineRoutes(opts: RouteOptions) {
|
|||
usageCounter,
|
||||
config$,
|
||||
getAlertIndicesAlias,
|
||||
alertingConfig,
|
||||
} = opts;
|
||||
|
||||
createRuleRoute(opts);
|
||||
|
@ -147,25 +150,26 @@ export function defineRoutes(opts: RouteOptions) {
|
|||
muteAlertRoute(router, licenseState);
|
||||
unmuteAlertRoute(router, licenseState);
|
||||
|
||||
// Maintenance Window - Internal APIs
|
||||
createMaintenanceWindowRouteInternal(router, licenseState);
|
||||
getMaintenanceWindowRouteInternal(router, licenseState);
|
||||
updateMaintenanceWindowRouteInternal(router, licenseState);
|
||||
deleteMaintenanceWindowRouteInternal(router, licenseState);
|
||||
findMaintenanceWindowsRouteInternal(router, licenseState);
|
||||
archiveMaintenanceWindowRouteInternal(router, licenseState);
|
||||
finishMaintenanceWindowRouteInternal(router, licenseState);
|
||||
getActiveMaintenanceWindowsRouteInternal(router, licenseState);
|
||||
bulkGetMaintenanceWindowRouteInternal(router, licenseState);
|
||||
|
||||
// Maintenance Window - External APIs
|
||||
getMaintenanceWindowRoute(router, licenseState);
|
||||
createMaintenanceWindowRoute(router, licenseState);
|
||||
deleteMaintenanceWindowRoute(router, licenseState);
|
||||
archiveMaintenanceWindowRoute(router, licenseState);
|
||||
unarchiveMaintenanceWindowRoute(router, licenseState);
|
||||
updateMaintenanceWindowRoute(router, licenseState);
|
||||
if (alertingConfig.maintenanceWindow.enabled) {
|
||||
// Maintenance Window - Internal APIs
|
||||
createMaintenanceWindowRouteInternal(router, licenseState);
|
||||
getMaintenanceWindowRouteInternal(router, licenseState);
|
||||
updateMaintenanceWindowRouteInternal(router, licenseState);
|
||||
deleteMaintenanceWindowRouteInternal(router, licenseState);
|
||||
findMaintenanceWindowsRouteInternal(router, licenseState);
|
||||
archiveMaintenanceWindowRouteInternal(router, licenseState);
|
||||
finishMaintenanceWindowRouteInternal(router, licenseState);
|
||||
getActiveMaintenanceWindowsRouteInternal(router, licenseState);
|
||||
bulkGetMaintenanceWindowRouteInternal(router, licenseState);
|
||||
|
||||
// Maintenance Window - External APIs
|
||||
getMaintenanceWindowRoute(router, licenseState);
|
||||
createMaintenanceWindowRoute(router, licenseState);
|
||||
deleteMaintenanceWindowRoute(router, licenseState);
|
||||
archiveMaintenanceWindowRoute(router, licenseState);
|
||||
unarchiveMaintenanceWindowRoute(router, licenseState);
|
||||
updateMaintenanceWindowRoute(router, licenseState);
|
||||
}
|
||||
// backfill APIs
|
||||
scheduleBackfillRoute(router, licenseState);
|
||||
getBackfillRoute(router, licenseState);
|
||||
|
@ -178,15 +182,18 @@ export function defineRoutes(opts: RouteOptions) {
|
|||
getRuleIdsWithGapsRoute(router, licenseState);
|
||||
getGapsSummaryByRuleIdsRoute(router, licenseState);
|
||||
|
||||
// Rules Settings APIs
|
||||
if (alertingConfig.rulesSettings.enabled) {
|
||||
getQueryDelaySettingsRoute(router, licenseState);
|
||||
updateQueryDelaySettingsRoute(router, licenseState);
|
||||
getFlappingSettingsRoute(router, licenseState);
|
||||
updateFlappingSettingsRoute(router, licenseState);
|
||||
}
|
||||
// Other APIs
|
||||
registerFieldsRoute(router, licenseState);
|
||||
getScheduleFrequencyRoute(router, licenseState);
|
||||
getQueryDelaySettingsRoute(router, licenseState);
|
||||
updateQueryDelaySettingsRoute(router, licenseState);
|
||||
getGlobalExecutionLogRoute(router, licenseState);
|
||||
getActionErrorLogRoute(router, licenseState);
|
||||
getFlappingSettingsRoute(router, licenseState);
|
||||
updateFlappingSettingsRoute(router, licenseState);
|
||||
runSoonRoute(router, licenseState);
|
||||
healthRoute(router, licenseState, encryptedSavedObjects);
|
||||
getGlobalExecutionKPIRoute(router, licenseState);
|
||||
|
|
|
@ -34,6 +34,39 @@ describe('createRuleRoute', () => {
|
|||
const docLinks = docLinksServiceMock.createSetupContract();
|
||||
const createdAt = new Date();
|
||||
const updatedAt = new Date();
|
||||
const alertingConfigMock = {
|
||||
healthCheck: {
|
||||
interval: '60m',
|
||||
},
|
||||
invalidateApiKeysTask: {
|
||||
interval: '5m',
|
||||
removalDelay: '1h',
|
||||
},
|
||||
enableFrameworkAlerts: true,
|
||||
cancelAlertsOnRuleTimeout: true,
|
||||
rules: {
|
||||
minimumScheduleInterval: {
|
||||
value: '1m',
|
||||
enforce: false,
|
||||
},
|
||||
maxScheduledPerMinute: 32000,
|
||||
run: {
|
||||
actions: {
|
||||
max: 100000,
|
||||
},
|
||||
alerts: {
|
||||
max: 1000,
|
||||
},
|
||||
},
|
||||
},
|
||||
rulesSettings: {
|
||||
enabled: true,
|
||||
cacheInterval: 60000,
|
||||
},
|
||||
maintenanceWindow: {
|
||||
enabled: true,
|
||||
},
|
||||
};
|
||||
const action: RuleAction = {
|
||||
actionTypeId: 'test',
|
||||
group: 'default',
|
||||
|
@ -154,6 +187,7 @@ describe('createRuleRoute', () => {
|
|||
encryptedSavedObjects,
|
||||
usageCounter: mockUsageCounter,
|
||||
docLinks,
|
||||
alertingConfig: alertingConfigMock,
|
||||
});
|
||||
|
||||
const [config, handler] = router.post.mock.calls[0];
|
||||
|
@ -268,6 +302,7 @@ describe('createRuleRoute', () => {
|
|||
encryptedSavedObjects,
|
||||
usageCounter: mockUsageCounter,
|
||||
docLinks,
|
||||
alertingConfig: alertingConfigMock,
|
||||
});
|
||||
|
||||
const [config, handler] = router.post.mock.calls[0];
|
||||
|
@ -386,6 +421,7 @@ describe('createRuleRoute', () => {
|
|||
encryptedSavedObjects,
|
||||
usageCounter: mockUsageCounter,
|
||||
docLinks,
|
||||
alertingConfig: alertingConfigMock,
|
||||
});
|
||||
|
||||
const [config, handler] = router.post.mock.calls[0];
|
||||
|
@ -505,6 +541,7 @@ describe('createRuleRoute', () => {
|
|||
encryptedSavedObjects,
|
||||
usageCounter: mockUsageCounter,
|
||||
docLinks,
|
||||
alertingConfig: alertingConfigMock,
|
||||
});
|
||||
|
||||
const [config, handler] = router.post.mock.calls[0];
|
||||
|
@ -612,7 +649,13 @@ describe('createRuleRoute', () => {
|
|||
const router = httpServiceMock.createRouter();
|
||||
const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true });
|
||||
|
||||
createRuleRoute({ router, licenseState, encryptedSavedObjects, docLinks });
|
||||
createRuleRoute({
|
||||
router,
|
||||
licenseState,
|
||||
encryptedSavedObjects,
|
||||
docLinks,
|
||||
alertingConfig: alertingConfigMock,
|
||||
});
|
||||
|
||||
const [, handler] = router.post.mock.calls[0];
|
||||
|
||||
|
@ -634,7 +677,13 @@ describe('createRuleRoute', () => {
|
|||
throw new Error('OMG');
|
||||
});
|
||||
|
||||
createRuleRoute({ router, licenseState, encryptedSavedObjects, docLinks });
|
||||
createRuleRoute({
|
||||
router,
|
||||
licenseState,
|
||||
encryptedSavedObjects,
|
||||
docLinks,
|
||||
alertingConfig: alertingConfigMock,
|
||||
});
|
||||
|
||||
const [, handler] = router.post.mock.calls[0];
|
||||
|
||||
|
@ -652,7 +701,13 @@ describe('createRuleRoute', () => {
|
|||
const router = httpServiceMock.createRouter();
|
||||
const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true });
|
||||
|
||||
createRuleRoute({ router, licenseState, encryptedSavedObjects, docLinks });
|
||||
createRuleRoute({
|
||||
router,
|
||||
licenseState,
|
||||
encryptedSavedObjects,
|
||||
docLinks,
|
||||
alertingConfig: alertingConfigMock,
|
||||
});
|
||||
|
||||
const [, handler] = router.post.mock.calls[0];
|
||||
|
||||
|
@ -684,6 +739,7 @@ describe('createRuleRoute', () => {
|
|||
encryptedSavedObjects,
|
||||
usageCounter: mockUsageCounter,
|
||||
docLinks,
|
||||
alertingConfig: alertingConfigMock,
|
||||
});
|
||||
|
||||
const [_, handler] = router.post.mock.calls[0];
|
||||
|
@ -767,6 +823,7 @@ describe('createRuleRoute', () => {
|
|||
encryptedSavedObjects,
|
||||
usageCounter: mockUsageCounter,
|
||||
docLinks,
|
||||
alertingConfig: alertingConfigMock,
|
||||
});
|
||||
|
||||
const [_, handler] = router.post.mock.calls[0];
|
||||
|
@ -824,6 +881,7 @@ describe('createRuleRoute', () => {
|
|||
encryptedSavedObjects,
|
||||
usageCounter: mockUsageCounter,
|
||||
docLinks,
|
||||
alertingConfig: alertingConfigMock,
|
||||
});
|
||||
|
||||
const [_, handler] = router.post.mock.calls[0];
|
||||
|
|
|
@ -71,6 +71,7 @@ export function generateAlertingConfig(): AlertingConfig {
|
|||
},
|
||||
},
|
||||
},
|
||||
rulesSettings: { cacheInterval: 60000 },
|
||||
rulesSettings: { enabled: true, cacheInterval: 60000 },
|
||||
maintenanceWindow: { enabled: true },
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,4 +7,7 @@
|
|||
|
||||
export interface TriggersActionsUiConfigType {
|
||||
enableExperimental: string[];
|
||||
rules: {
|
||||
enabled: boolean;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -14,10 +14,12 @@ import { useKibana } from '../../../common/lib/kibana';
|
|||
export const RulesSettingsLink = () => {
|
||||
const [isVisible, setIsVisible] = useState<boolean>(false);
|
||||
const {
|
||||
application: { capabilities },
|
||||
application: {
|
||||
capabilities: { rulesSettings = {} },
|
||||
},
|
||||
} = useKibana().services;
|
||||
|
||||
const { show, readFlappingSettingsUI, readQueryDelaySettingsUI } = capabilities.rulesSettings;
|
||||
const { show, readFlappingSettingsUI, readQueryDelaySettingsUI } = rulesSettings;
|
||||
|
||||
if (!show || (!readFlappingSettingsUI && !readQueryDelaySettingsUI)) {
|
||||
return null;
|
||||
|
|
|
@ -240,59 +240,61 @@ export class Plugin
|
|||
});
|
||||
}
|
||||
|
||||
plugins.management.sections.section.insightsAndAlerting.registerApp({
|
||||
id: PLUGIN_ID,
|
||||
title: featureTitle,
|
||||
order: 1,
|
||||
async mount(params: ManagementAppMountParams) {
|
||||
const [coreStart, pluginsStart] = (await core.getStartServices()) as [
|
||||
CoreStart,
|
||||
PluginsStart,
|
||||
unknown
|
||||
];
|
||||
if (this.config.rules.enabled) {
|
||||
plugins.management.sections.section.insightsAndAlerting.registerApp({
|
||||
id: PLUGIN_ID,
|
||||
title: featureTitle,
|
||||
order: 1,
|
||||
async mount(params: ManagementAppMountParams) {
|
||||
const [coreStart, pluginsStart] = (await core.getStartServices()) as [
|
||||
CoreStart,
|
||||
PluginsStart,
|
||||
unknown
|
||||
];
|
||||
|
||||
const { renderApp } = await import('./application/rules_app');
|
||||
const { renderApp } = await import('./application/rules_app');
|
||||
|
||||
// The `/api/features` endpoint requires the "Global All" Kibana privilege. Users with a
|
||||
// subset of this privilege are not authorized to access this endpoint and will receive a 404
|
||||
// error that causes the Alerting view to fail to load.
|
||||
let kibanaFeatures: KibanaFeature[];
|
||||
try {
|
||||
kibanaFeatures = await pluginsStart.features.getFeatures();
|
||||
} catch (err) {
|
||||
kibanaFeatures = [];
|
||||
}
|
||||
// The `/api/features` endpoint requires the "Global All" Kibana privilege. Users with a
|
||||
// subset of this privilege are not authorized to access this endpoint and will receive a 404
|
||||
// error that causes the Alerting view to fail to load.
|
||||
let kibanaFeatures: KibanaFeature[];
|
||||
try {
|
||||
kibanaFeatures = await pluginsStart.features.getFeatures();
|
||||
} catch (err) {
|
||||
kibanaFeatures = [];
|
||||
}
|
||||
|
||||
return renderApp({
|
||||
...coreStart,
|
||||
actions: plugins.actions,
|
||||
dashboard: pluginsStart.dashboard,
|
||||
cloud: plugins.cloud,
|
||||
data: pluginsStart.data,
|
||||
dataViews: pluginsStart.dataViews,
|
||||
dataViewEditor: pluginsStart.dataViewEditor,
|
||||
charts: pluginsStart.charts,
|
||||
alerting: pluginsStart.alerting,
|
||||
spaces: pluginsStart.spaces,
|
||||
unifiedSearch: pluginsStart.unifiedSearch,
|
||||
isCloud: Boolean(plugins.cloud?.isCloudEnabled),
|
||||
element: params.element,
|
||||
theme: params.theme,
|
||||
storage: new Storage(window.localStorage),
|
||||
setBreadcrumbs: params.setBreadcrumbs,
|
||||
history: params.history,
|
||||
actionTypeRegistry,
|
||||
ruleTypeRegistry,
|
||||
kibanaFeatures,
|
||||
licensing: pluginsStart.licensing,
|
||||
expressions: pluginsStart.expressions,
|
||||
isServerless: !!pluginsStart.serverless,
|
||||
fieldFormats: pluginsStart.fieldFormats,
|
||||
lens: pluginsStart.lens,
|
||||
fieldsMetadata: pluginsStart.fieldsMetadata,
|
||||
});
|
||||
},
|
||||
});
|
||||
return renderApp({
|
||||
...coreStart,
|
||||
actions: plugins.actions,
|
||||
dashboard: pluginsStart.dashboard,
|
||||
cloud: plugins.cloud,
|
||||
data: pluginsStart.data,
|
||||
dataViews: pluginsStart.dataViews,
|
||||
dataViewEditor: pluginsStart.dataViewEditor,
|
||||
charts: pluginsStart.charts,
|
||||
alerting: pluginsStart.alerting,
|
||||
spaces: pluginsStart.spaces,
|
||||
unifiedSearch: pluginsStart.unifiedSearch,
|
||||
isCloud: Boolean(plugins.cloud?.isCloudEnabled),
|
||||
element: params.element,
|
||||
theme: params.theme,
|
||||
storage: new Storage(window.localStorage),
|
||||
setBreadcrumbs: params.setBreadcrumbs,
|
||||
history: params.history,
|
||||
actionTypeRegistry,
|
||||
ruleTypeRegistry,
|
||||
kibanaFeatures,
|
||||
licensing: pluginsStart.licensing,
|
||||
expressions: pluginsStart.expressions,
|
||||
isServerless: !!pluginsStart.serverless,
|
||||
fieldFormats: pluginsStart.fieldFormats,
|
||||
lens: pluginsStart.lens,
|
||||
fieldsMetadata: pluginsStart.fieldsMetadata,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
plugins.management.sections.section.insightsAndAlerting.registerApp({
|
||||
id: CONNECTORS_PLUGIN_ID,
|
||||
|
|
|
@ -19,6 +19,9 @@ import {
|
|||
const allowedExperimentalValues = getExperimentalAllowedValues();
|
||||
|
||||
export const configSchema = schema.object({
|
||||
rules: schema.object({
|
||||
enabled: schema.boolean({ defaultValue: true }),
|
||||
}),
|
||||
enableGeoTrackingThresholdAlert: schema.maybe(schema.boolean({ defaultValue: false })),
|
||||
enableExperimental: schema.arrayOf(schema.string(), {
|
||||
defaultValue: () => [],
|
||||
|
|
|
@ -14,6 +14,9 @@ export { DEFAULT_GROUPS, TIME_SERIES_BUCKET_SELECTOR_FIELD } from './data';
|
|||
|
||||
export const config: PluginConfigDescriptor<ConfigSchema> = {
|
||||
exposeToBrowser: {
|
||||
rules: {
|
||||
enabled: true,
|
||||
},
|
||||
enableGeoTrackingThresholdAlert: true,
|
||||
enableExperimental: true,
|
||||
},
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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 { createTestConfig } from '../../common/config';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default createTestConfig('security_and_spaces', {
|
||||
disabledPlugins: ['alerting.maintenanceWindow', 'alerting.rulesSettings'],
|
||||
license: 'trial',
|
||||
ssl: true,
|
||||
enableActionsProxy: true,
|
||||
publicBaseUrl: true,
|
||||
testFiles: [require.resolve('./tests')],
|
||||
useDedicatedTaskRunner: true,
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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 type { FtrProviderContext } from '../../../../common/ftr_provider_context';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function alertingApiIntegrationTests({ loadTestFile }: FtrProviderContext) {
|
||||
describe('alerting api integration security and spaces disabled - Group 6', function () {
|
||||
loadTestFile(require.resolve('./maintenance_window_disabled'));
|
||||
loadTestFile(require.resolve('./rules_settings_disabled'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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 type { FtrProviderContext } from '../../../../../common/ftr_provider_context';
|
||||
import { setupSpacesAndUsers, tearDown } from '../../../setup';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function maintenanceWindowDisabledTests({
|
||||
loadTestFile,
|
||||
getService,
|
||||
}: FtrProviderContext) {
|
||||
describe('Maintenance Window Disabled - Group 3', () => {
|
||||
before(async () => {
|
||||
await setupSpacesAndUsers(getService);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await tearDown(getService);
|
||||
});
|
||||
|
||||
loadTestFile(require.resolve('./maintenance_window_api_disabled'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import { UserAtSpaceScenarios } from '../../../scenarios';
|
||||
import { getUrlPrefix } from '../../../../common/lib';
|
||||
import type { FtrProviderContext } from '../../../../../common/ftr_provider_context';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function maintenanceWindowApiDisabledTests({ getService }: FtrProviderContext) {
|
||||
const supertestWithoutAuth = getService('supertestWithoutAuth');
|
||||
|
||||
describe('maintenance window API disabled', () => {
|
||||
const createParams = {
|
||||
title: 'test-maintenance-window',
|
||||
duration: 60 * 60 * 1000, // 1 hr
|
||||
r_rule: {
|
||||
dtstart: new Date().toISOString(),
|
||||
tzid: 'UTC',
|
||||
freq: 2, // weekly
|
||||
},
|
||||
};
|
||||
|
||||
for (const scenario of UserAtSpaceScenarios) {
|
||||
const { user, space } = scenario;
|
||||
describe(scenario.id, () => {
|
||||
it('should return 404 when trying to create a maintenance window', async () => {
|
||||
const response = await supertestWithoutAuth
|
||||
.post(`${getUrlPrefix(space.id)}/internal/alerting/rules/maintenance_window`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password)
|
||||
.send(createParams);
|
||||
|
||||
expect(response.statusCode).to.eql(404);
|
||||
expect(response.body).to.eql({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message: 'Not Found',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 404 when trying to get a maintenance window', async () => {
|
||||
const response = await supertestWithoutAuth
|
||||
.get(`${getUrlPrefix(space.id)}/internal/alerting/rules/maintenance_window/some-id`)
|
||||
.auth(user.username, user.password);
|
||||
|
||||
expect(response.statusCode).to.eql(404);
|
||||
expect(response.body).to.eql({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message: 'Not Found',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 404 when trying to update a maintenance window', async () => {
|
||||
const response = await supertestWithoutAuth
|
||||
.post(`${getUrlPrefix(space.id)}/internal/alerting/rules/maintenance_window/some-id`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password)
|
||||
.send(createParams);
|
||||
|
||||
expect(response.statusCode).to.eql(404);
|
||||
expect(response.body).to.eql({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message: 'Not Found',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 404 when trying to delete a maintenance window', async () => {
|
||||
const response = await supertestWithoutAuth
|
||||
.delete(`${getUrlPrefix(space.id)}/internal/alerting/rules/maintenance_window/some-id`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password);
|
||||
|
||||
expect(response.statusCode).to.eql(404);
|
||||
expect(response.body).to.eql({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message: 'Not Found',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 404 when trying to archive a maintenance window', async () => {
|
||||
const response = await supertestWithoutAuth
|
||||
.post(
|
||||
`${getUrlPrefix(
|
||||
space.id
|
||||
)}/internal/alerting/rules/maintenance_window/some-id/_archive`
|
||||
)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password);
|
||||
|
||||
expect(response.statusCode).to.eql(404);
|
||||
expect(response.body).to.eql({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message: 'Not Found',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 404 when trying to finish a maintenance window', async () => {
|
||||
const response = await supertestWithoutAuth
|
||||
.post(
|
||||
`${getUrlPrefix(space.id)}/internal/alerting/rules/maintenance_window/some-id/_finish`
|
||||
)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password);
|
||||
|
||||
expect(response.statusCode).to.eql(404);
|
||||
expect(response.body).to.eql({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message: 'Not Found',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 404 when trying to find maintenance windows', async () => {
|
||||
const response = await supertestWithoutAuth
|
||||
.get(`${getUrlPrefix(space.id)}/internal/alerting/rules/maintenance_window/_find`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password);
|
||||
|
||||
expect(response.statusCode).to.eql(404);
|
||||
expect(response.body).to.eql({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message: 'Not Found',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 404 when trying to get active maintenance windows', async () => {
|
||||
const response = await supertestWithoutAuth
|
||||
.get(`${getUrlPrefix(space.id)}/internal/alerting/rules/maintenance_window/_active`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password);
|
||||
|
||||
expect(response.statusCode).to.eql(404);
|
||||
expect(response.body).to.eql({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message: 'Not Found',
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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 type { FtrProviderContext } from '../../../../../common/ftr_provider_context';
|
||||
import { setupSpacesAndUsers, tearDown } from '../../../setup';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function rulesSettingsDisabledTests({
|
||||
loadTestFile,
|
||||
getService,
|
||||
}: FtrProviderContext) {
|
||||
describe('Rules Settings Disabled - Group 6', () => {
|
||||
before(async () => {
|
||||
await setupSpacesAndUsers(getService);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await tearDown(getService);
|
||||
});
|
||||
|
||||
loadTestFile(require.resolve('./rules_settings_api_disabled'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import { UserAtSpaceScenarios } from '../../../scenarios';
|
||||
import { getUrlPrefix } from '../../../../common/lib';
|
||||
import type { FtrProviderContext } from '../../../../../common/ftr_provider_context';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function rulesSettingsApiDisabledTests({ getService }: FtrProviderContext) {
|
||||
const supertestWithoutAuth = getService('supertestWithoutAuth');
|
||||
|
||||
describe('rules settings API disabled', () => {
|
||||
const flappingSettingsParams = {
|
||||
enabled: true,
|
||||
look_back_window: 10,
|
||||
status_change_threshold: 5,
|
||||
};
|
||||
|
||||
const queryDelaySettingsParams = {
|
||||
delay: 30,
|
||||
};
|
||||
|
||||
for (const scenario of UserAtSpaceScenarios) {
|
||||
const { user, space } = scenario;
|
||||
describe(scenario.id, () => {
|
||||
it('should return 404 when trying to get flapping settings', async () => {
|
||||
const response = await supertestWithoutAuth
|
||||
.get(`${getUrlPrefix(space.id)}/internal/alerting/rules/settings/_flapping`)
|
||||
.auth(user.username, user.password);
|
||||
|
||||
expect(response.statusCode).to.eql(404);
|
||||
expect(response.body).to.eql({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message: 'Not Found',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 404 when trying to update flapping settings', async () => {
|
||||
const response = await supertestWithoutAuth
|
||||
.post(`${getUrlPrefix(space.id)}/internal/alerting/rules/settings/_flapping`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password)
|
||||
.send(flappingSettingsParams);
|
||||
|
||||
expect(response.statusCode).to.eql(404);
|
||||
expect(response.body).to.eql({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message: 'Not Found',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 404 when trying to get query delay settings', async () => {
|
||||
const response = await supertestWithoutAuth
|
||||
.get(`${getUrlPrefix(space.id)}/internal/alerting/rules/settings/_query_delay`)
|
||||
.auth(user.username, user.password);
|
||||
|
||||
expect(response.statusCode).to.eql(404);
|
||||
expect(response.body).to.eql({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message: 'Not Found',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 404 when trying to update query delay settings', async () => {
|
||||
const response = await supertestWithoutAuth
|
||||
.post(`${getUrlPrefix(space.id)}/internal/alerting/rules/settings/_query_delay`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password)
|
||||
.send(queryDelaySettingsParams);
|
||||
|
||||
expect(response.statusCode).to.eql(404);
|
||||
expect(response.body).to.eql({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message: 'Not Found',
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
|
@ -7,108 +7,110 @@
|
|||
|
||||
import { login } from '../../../tasks/login';
|
||||
import { visit } from '../../../tasks/navigation';
|
||||
import { ALERTS_SUMMARY_PROMPT, GET_STARTED_PAGE } from '../constants';
|
||||
import { ALERT_SUMMARY_URL, ALERTS_URL, RULES_LANDING_URL } from '../../../urls/navigation';
|
||||
import { ALERTS_SUMMARY_PROMPT, GET_STARTED_PAGE } from '../../../screens/ai_soc';
|
||||
import {
|
||||
ALERT_SUMMARY_URL,
|
||||
ALERTS_URL,
|
||||
MAINTENANCE_WINDOW_URL,
|
||||
RULES_LANDING_URL,
|
||||
STACK_RULES_URL,
|
||||
} from '../../../urls/navigation';
|
||||
|
||||
const testPageAccess = () => {
|
||||
it('should show page or redirect depending on capabilities', () => {
|
||||
visit(ALERT_SUMMARY_URL);
|
||||
cy.get(ALERTS_SUMMARY_PROMPT).should('exist');
|
||||
|
||||
// should redirect out from alerts to get started page
|
||||
visit(ALERTS_URL);
|
||||
cy.get(GET_STARTED_PAGE).should('exist');
|
||||
|
||||
// should redirect out from rules to get started page
|
||||
visit(RULES_LANDING_URL);
|
||||
cy.get(GET_STARTED_PAGE).should('exist');
|
||||
});
|
||||
};
|
||||
const MANAGEMENT_PAGE_DESCRIPTION =
|
||||
'Manage data and indices, oversee rules and connectors, organize saved objects and files, and create API keys in a central location.';
|
||||
|
||||
describe('Capabilities', { tags: '@serverless' }, () => {
|
||||
describe('Admin user capabilities', () => {
|
||||
beforeEach(() => {
|
||||
login('admin');
|
||||
});
|
||||
|
||||
testPageAccess();
|
||||
});
|
||||
|
||||
describe('User with siem v1 role', () => {
|
||||
const roleDescriptor = {
|
||||
elasticsearch: {
|
||||
indices: [
|
||||
{
|
||||
names: ['*'],
|
||||
privileges: ['all'],
|
||||
const userRoles = [
|
||||
{
|
||||
name: 'Admin user',
|
||||
loginAs: 'admin',
|
||||
setup: () => {}, // No additional setup needed
|
||||
teardown: () => {}, // No teardown needed
|
||||
},
|
||||
{
|
||||
name: 'User with siem v1 role',
|
||||
loginAs: 'siemv1',
|
||||
setup: () => {
|
||||
cy.task('createServerlessCustomRole', {
|
||||
roleDescriptor: {
|
||||
elasticsearch: {
|
||||
indices: [{ names: ['*'], privileges: ['all'] }],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
feature: { siem: ['all'], fleet: ['all'] },
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
roleName: 'siemv1',
|
||||
});
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
siem: ['all'],
|
||||
fleet: ['all'],
|
||||
teardown: () => {
|
||||
cy.task('deleteServerlessCustomRole', 'siemv1');
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'User with siem v2 role',
|
||||
loginAs: 'siemV2',
|
||||
setup: () => {
|
||||
cy.task('createServerlessCustomRole', {
|
||||
roleDescriptor: {
|
||||
elasticsearch: {
|
||||
indices: [{ names: ['*'], privileges: ['all'] }],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
feature: { siemV2: ['all'], fleet: ['all'] },
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
};
|
||||
roleName: 'siemV2',
|
||||
});
|
||||
},
|
||||
teardown: () => {
|
||||
cy.task('deleteServerlessCustomRole', 'siemV2');
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
before(() => {
|
||||
cy.task('createServerlessCustomRole', {
|
||||
roleDescriptor,
|
||||
roleName: 'siemv1',
|
||||
// Iterate through each user role
|
||||
userRoles.forEach((role) => {
|
||||
describe(`${role.name} capabilities`, () => {
|
||||
before(() => role.setup());
|
||||
|
||||
beforeEach(() => {
|
||||
login(role.loginAs);
|
||||
});
|
||||
|
||||
after(() => role.teardown());
|
||||
|
||||
// Individual test cases with clear descriptions
|
||||
it('should show alert summary prompt when visiting alert summary page', () => {
|
||||
visit(ALERT_SUMMARY_URL);
|
||||
cy.get(ALERTS_SUMMARY_PROMPT).should('exist');
|
||||
});
|
||||
|
||||
it('should redirect from alerts to get started page', () => {
|
||||
visit(ALERTS_URL);
|
||||
cy.get(GET_STARTED_PAGE).should('exist');
|
||||
});
|
||||
|
||||
it('should redirect from rules to get started page', () => {
|
||||
visit(RULES_LANDING_URL);
|
||||
cy.get(GET_STARTED_PAGE).should('exist');
|
||||
});
|
||||
|
||||
it('should redirect from stack rules to main management page', () => {
|
||||
visit(STACK_RULES_URL);
|
||||
cy.contains(MANAGEMENT_PAGE_DESCRIPTION).should('exist');
|
||||
});
|
||||
|
||||
it('should redirect from maintenance window to main management page', () => {
|
||||
visit(MAINTENANCE_WINDOW_URL);
|
||||
cy.contains(MANAGEMENT_PAGE_DESCRIPTION).should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login('siemv1');
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cy.task('deleteServerlessCustomRole', 'siemv1');
|
||||
});
|
||||
|
||||
testPageAccess();
|
||||
});
|
||||
|
||||
describe('User with siem v2 role', () => {
|
||||
const roleDescriptor = {
|
||||
elasticsearch: {
|
||||
indices: [
|
||||
{
|
||||
names: ['*'],
|
||||
privileges: ['all'],
|
||||
},
|
||||
],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
siemV2: ['all'],
|
||||
fleet: ['all'],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
before(() => {
|
||||
cy.task('createServerlessCustomRole', {
|
||||
roleDescriptor,
|
||||
roleName: 'siemV2',
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login('siemV2');
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cy.task('deleteServerlessCustomRole', 'siemV2');
|
||||
});
|
||||
|
||||
testPageAccess();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,8 +4,3 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export const ALERTS_SUMMARY_PROMPT = '[data-test-subj="alert-summary-landing-page-prompt"]';
|
||||
export const GET_STARTED_PAGE = '[data-test-subj="onboarding-hub-page"]';
|
||||
export const AI_SOC_NAVIGATION =
|
||||
'[data-test-subj="nav-item nav-item-security_solution_ai_nav nav-item-id-security_solution_ai_nav"]';
|
||||
|
|
|
@ -8,15 +8,11 @@
|
|||
import { login } from '../../../tasks/login';
|
||||
import { visit } from '../../../tasks/navigation';
|
||||
import { GET_STARTED_URL } from '../../../urls/navigation';
|
||||
import { AI_SOC_NAVIGATION } from '../constants';
|
||||
import { AI_SOC_NAVIGATION } from '../../../screens/ai_soc';
|
||||
|
||||
const visibleLinks = ['discover', 'attack_discovery', 'case', 'alert_summary', 'configurations'];
|
||||
|
||||
const notVisibleLinks = [
|
||||
// 'machine_learning-landing', -- TODO comment out when ML is turned off
|
||||
'alerts',
|
||||
'rules',
|
||||
];
|
||||
const notVisibleLinks = ['machine_learning-landing', 'alerts', 'rules'];
|
||||
|
||||
describe('AI$DSOC Navigation', { tags: '@serverless' }, () => {
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export const ALERTS_SUMMARY_PROMPT = '[data-test-subj="alert-summary-landing-page-prompt"]';
|
||||
export const GET_STARTED_PAGE = '[data-test-subj="onboarding-hub-page"]';
|
||||
export const AI_SOC_NAVIGATION =
|
||||
'[data-test-subj="nav-item nav-item-security_solution_ai_nav nav-item-id-security_solution_ai_nav"]';
|
|
@ -88,3 +88,7 @@ export const ASSET_INVENTORY_URL = '/app/security/asset_inventory';
|
|||
|
||||
// Custom Role Creation
|
||||
export const CUSTOM_ROLES_URL = 'app/management/security/roles/edit';
|
||||
|
||||
// Alerting
|
||||
export const STACK_RULES_URL = 'app/management/insightsAndAlerting/triggersActions/rules';
|
||||
export const MAINTENANCE_WINDOW_URL = 'app/management/insightsAndAlerting/maintenanceWindows';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue