mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Security Solution] Adds RBAC for Assistant (#163031)
## Summary
Adds `All`/`None` RBAC for the Elastic AI Assistant within the Security
app via Kibana feature privileges, and also via serverless PLI App
Features for the Security `complete` product (see
https://github.com/elastic/security-team/issues/7023).
Added as high-level category to enable future support of sub-features
(included sample `Create Conversation` sub-feature plumbed as example).
<p align="center">
<img width="500"
src="b42ab3fe
-65e1-49b9-a379-262f2438c0eb"
/>
</p>
Note: Since [`minimumLicense:
'enterprise'`](https://github.com/elastic/kibana/pull/163031/files#diff-56de8b6234daf4e0e69efe680e5a4afc4f88d152243b773d90c3991fa9dabc19R28)
is configured on this privilege, when the license check isn't satisfied,
the privilege will be hidden (not disabled).
## Testing
Feature is available for `enterprise` licenses and when `All` privilege
is set, otherwise Assistant is hidden in Timeline, all `Chat` UI
elements are hidden, and the `cmd/ctrl + ;` shortcut is unavailable.
---
### On Prem Testing:
Create two roles, one for each `all`/`none` Security Elastic AI
Assistant privilege (via Dev Tools):
<details><summary>PUT /_security/role/assistant_all</summary>
<p>
``` ts
PUT /_security/role/assistant_all
{
"cluster": [
"all"
],
"indices": [
{
"names": [
"*"
],
"privileges": [
"all"
],
"field_security": {
"grant": [
"*"
],
"except": []
},
"allow_restricted_indices": false
}
],
"applications": [
{
"application": "kibana-.kibana",
"privileges": [
"feature_securitySolutionAssistant.minimal_all",
"feature_siem.all",
"feature_securitySolutionCases.all",
"feature_actions.all"
],
"resources": [
"*"
]
}
],
"run_as": [],
"metadata": {},
"transient_metadata": {
"enabled": true
}
}
```
</p>
</details>
<details><summary>PUT /_security/role/assistant_none</summary>
<p>
``` ts
PUT /_security/role/assistant_none
{
"cluster": [
"all"
],
"indices": [
{
"names": [
"*"
],
"privileges": [
"all"
],
"field_security": {
"grant": [
"*"
],
"except": []
},
"allow_restricted_indices": false
}
],
"applications": [
{
"application": "kibana-.kibana",
"privileges": [
"feature_siem.all",
"feature_securitySolutionCases.all",
"feature_actions.all"
],
"resources": [
"*"
]
}
],
"run_as": [],
"metadata": {},
"transient_metadata": {
"enabled": true
}
}
```
</p>
</details>
Create a new `assistant_user` (assigned both roles above), log in and
test assistant availability, then remove one role at a time testing
each:
<details><summary>POST /_security/user/assistant_user (ALL)</summary>
<p>
``` ts
POST /_security/user/assistant_user
{
"username": "assistant_user",
"password": "changeme",
"roles": [
"assistant_all",
"assistant_none"
],
"full_name": "Assistant User",
"email": "assistant-user@elastic.co",
"metadata": {},
"enabled": true
}
```
</p>
</details>
Test that assistant is available in UI via `Chat` buttons and shortcut
keys.
<details><summary>PUT /_security/user/assistant_user (NONE)</summary>
<p>
``` ts
PUT /_security/user/assistant_user
{
"username": "assistant_user",
"roles": [
"assistant_none"
],
"full_name": "Assistant User",
"email": "assistant-user@elastic.co",
"metadata": {},
"enabled": true
}
```
</p>
</details>
Test that assistant is **NOT** available in UI via `Chat` buttons or
shortcut keys.
---
### Serverless Testing:
To test with the Assistant available, set `productTypes` to `complete`
in `config/serverless.security.yml`
```
xpack.securitySolutionServerless.productTypes:
[
{ product_line: 'security', product_tier: 'complete' },
{ product_line: 'endpoint', product_tier: 'complete' },
]
```
otherwise to test without the Assistant, pick a different product type like `essentials`:
```
xpack.securitySolutionServerless.productTypes:
[
{ product_line: 'security', product_tier: 'essentials' },
{ product_line: 'endpoint', product_tier: 'essentials' },
]
```
Then start Serverless Kibana: `yarn serverless-security`
---
### Checklist
Delete any items that are not applicable to this PR.
- [X] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials
- [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
This commit is contained in:
parent
0a74fa03a0
commit
6acf72f25c
26 changed files with 281 additions and 10 deletions
|
@ -20,6 +20,7 @@ export { SecurityPageName } from '@kbn/security-solution-navigation';
|
|||
*/
|
||||
export const APP_ID = 'securitySolution' as const;
|
||||
export const APP_UI_ID = 'securitySolutionUI' as const;
|
||||
export const ASSISTANT_FEATURE_ID = 'securitySolutionAssistant' as const;
|
||||
export const CASES_FEATURE_ID = 'securitySolutionCases' as const;
|
||||
export const SERVER_APP_ID = 'siem' as const;
|
||||
export const APP_NAME = 'Security' as const;
|
||||
|
|
|
@ -55,6 +55,13 @@ export enum AppFeatureSecurityKey {
|
|||
osqueryAutomatedResponseActions = 'osquery_automated_response_actions',
|
||||
}
|
||||
|
||||
export enum AppFeatureAssistantKey {
|
||||
/**
|
||||
* Enables Elastic AI Assistant
|
||||
*/
|
||||
assistant = 'assistant',
|
||||
}
|
||||
|
||||
export enum AppFeatureCasesKey {
|
||||
/**
|
||||
* Enables Cases Connectors
|
||||
|
@ -63,9 +70,13 @@ export enum AppFeatureCasesKey {
|
|||
}
|
||||
|
||||
// Merges the two enums.
|
||||
export type AppFeatureKey = AppFeatureSecurityKey | AppFeatureCasesKey;
|
||||
export type AppFeatureKey = AppFeatureSecurityKey | AppFeatureCasesKey | AppFeatureAssistantKey;
|
||||
export type AppFeatureKeys = AppFeatureKey[];
|
||||
|
||||
// We need to merge the value and the type and export both to replicate how enum works.
|
||||
export const AppFeatureKey = { ...AppFeatureSecurityKey, ...AppFeatureCasesKey };
|
||||
export const AppFeatureKey = {
|
||||
...AppFeatureSecurityKey,
|
||||
...AppFeatureCasesKey,
|
||||
...AppFeatureAssistantKey,
|
||||
};
|
||||
export const ALL_APP_FEATURE_KEYS = Object.freeze(Object.values(AppFeatureKey));
|
||||
|
|
|
@ -63,6 +63,7 @@ export const secAll: Role = {
|
|||
{
|
||||
feature: {
|
||||
siem: ['all'],
|
||||
securitySolutionAssistant: ['all'],
|
||||
securitySolutionCases: ['all'],
|
||||
actions: ['all'],
|
||||
actionsSimulators: ['all'],
|
||||
|
@ -94,6 +95,7 @@ export const secReadCasesAll: Role = {
|
|||
{
|
||||
feature: {
|
||||
siem: ['read'],
|
||||
securitySolutionAssistant: ['all'],
|
||||
securitySolutionCases: ['all'],
|
||||
actions: ['all'],
|
||||
actionsSimulators: ['all'],
|
||||
|
@ -125,6 +127,7 @@ export const secAllCasesOnlyReadDelete: Role = {
|
|||
{
|
||||
feature: {
|
||||
siem: ['all'],
|
||||
securitySolutionAssistant: ['all'],
|
||||
securitySolutionCases: ['cases_read', 'cases_delete'],
|
||||
actions: ['all'],
|
||||
actionsSimulators: ['all'],
|
||||
|
@ -156,6 +159,7 @@ export const secAllCasesNoDelete: Role = {
|
|||
{
|
||||
feature: {
|
||||
siem: ['all'],
|
||||
securitySolutionAssistant: ['all'],
|
||||
securitySolutionCases: ['minimal_all'],
|
||||
actions: ['all'],
|
||||
actionsSimulators: ['all'],
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
|
||||
import { useLicense } from '../../common/hooks/use_license';
|
||||
import { useKibana } from '../../common/lib/kibana';
|
||||
import { ASSISTANT_FEATURE_ID } from '../../../common/constants';
|
||||
|
||||
export interface UseAssistantAvailability {
|
||||
// True when user is Enterprise. When false, the Assistant is disabled and unavailable
|
||||
|
@ -16,11 +18,11 @@ export interface UseAssistantAvailability {
|
|||
|
||||
export const useAssistantAvailability = (): UseAssistantAvailability => {
|
||||
const isEnterprise = useLicense().isEnterprise();
|
||||
const capabilities = useKibana().services.application.capabilities;
|
||||
const isAssistantEnabled = capabilities[ASSISTANT_FEATURE_ID]?.['ai-assistant'] === true;
|
||||
|
||||
return {
|
||||
isAssistantEnabled: isEnterprise,
|
||||
// TODO: RBAC check (https://github.com/elastic/security-team/issues/6932)
|
||||
// Leaving as a placeholder for RBAC as the same behavior will be required
|
||||
// When false, the Assistant is hidden and unavailable
|
||||
hasAssistantPrivilege: true,
|
||||
hasAssistantPrivilege: isAssistantEnabled,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -35,7 +35,7 @@ import {
|
|||
import type { FieldHook } from '../../shared_imports';
|
||||
import { SUB_PLUGINS_REDUCER } from './utils';
|
||||
import { createSecuritySolutionStorageMock, localStorageMock } from './mock_local_storage';
|
||||
import { CASES_FEATURE_ID } from '../../../common/constants';
|
||||
import { ASSISTANT_FEATURE_ID, CASES_FEATURE_ID } from '../../../common/constants';
|
||||
import { UserPrivilegesProvider } from '../components/user_privileges/user_privileges_context';
|
||||
|
||||
const state: State = mockGlobalState;
|
||||
|
@ -125,6 +125,7 @@ const TestProvidersWithPrivilegesComponent: React.FC<Props> = ({
|
|||
{
|
||||
siem: { show: true, crud: true },
|
||||
[CASES_FEATURE_ID]: { read_cases: true, crud_cases: false },
|
||||
[ASSISTANT_FEATURE_ID]: { 'ai-assistant': true },
|
||||
} as unknown as Capabilities
|
||||
}
|
||||
>
|
||||
|
|
|
@ -113,6 +113,9 @@ jest.mock('../../../../common/lib/kibana', () => {
|
|||
save: true,
|
||||
show: true,
|
||||
},
|
||||
siem: {
|
||||
'ai-assistant': true,
|
||||
},
|
||||
},
|
||||
},
|
||||
data: {
|
||||
|
|
|
@ -21,7 +21,11 @@ import { coreMock } from '@kbn/core/public/mocks';
|
|||
import { mockCasesContext } from '@kbn/cases-plugin/public/mocks/mock_cases_context';
|
||||
import { useTimelineEventsDetails } from '../../../containers/details';
|
||||
import { allCasesPermissions } from '../../../../cases_test_utils';
|
||||
import { DEFAULT_ALERTS_INDEX, DEFAULT_PREVIEW_INDEX } from '../../../../../common/constants';
|
||||
import {
|
||||
DEFAULT_ALERTS_INDEX,
|
||||
DEFAULT_PREVIEW_INDEX,
|
||||
ASSISTANT_FEATURE_ID,
|
||||
} from '../../../../../common/constants';
|
||||
|
||||
const ecsData: Ecs = {
|
||||
_id: '1',
|
||||
|
@ -138,6 +142,13 @@ describe('event details panel component', () => {
|
|||
(KibanaServices.get as jest.Mock).mockReturnValue(coreStartMock);
|
||||
(useKibana as jest.Mock).mockReturnValue({
|
||||
services: {
|
||||
application: {
|
||||
capabilities: {
|
||||
[ASSISTANT_FEATURE_ID]: {
|
||||
'ai-assistant': true,
|
||||
},
|
||||
},
|
||||
},
|
||||
uiSettings: {
|
||||
get: jest.fn().mockReturnValue([]),
|
||||
},
|
||||
|
|
|
@ -48,6 +48,25 @@ const CASES_APP_FEATURE_CONFIG = {
|
|||
},
|
||||
};
|
||||
|
||||
const ASSISTANT_BASE_CONFIG = {
|
||||
bar: 'bar',
|
||||
};
|
||||
|
||||
const ASSISTANT_APP_FEATURE_CONFIG = {
|
||||
'test-assistant-feature': {
|
||||
privileges: {
|
||||
all: {
|
||||
ui: ['test-assistant-capability'],
|
||||
api: ['test-assistant-capability'],
|
||||
},
|
||||
read: {
|
||||
ui: ['test-assistant-capability'],
|
||||
api: ['test-assistant-capability'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
jest.mock('./security_kibana_features', () => {
|
||||
return {
|
||||
getSecurityBaseKibanaFeature: jest.fn(() => SECURITY_BASE_CONFIG),
|
||||
|
@ -75,6 +94,20 @@ jest.mock('./security_cases_kibana_sub_features', () => {
|
|||
};
|
||||
});
|
||||
|
||||
jest.mock('./security_assistant_kibana_features', () => {
|
||||
return {
|
||||
getAssistantBaseKibanaFeature: jest.fn(() => ASSISTANT_BASE_CONFIG),
|
||||
getAssistantBaseKibanaSubFeatureIds: jest.fn(() => ['subFeature1']),
|
||||
getAssistantAppFeaturesConfig: jest.fn(() => ASSISTANT_APP_FEATURE_CONFIG),
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('./security_assistant_kibana_sub_features', () => {
|
||||
return {
|
||||
assistantSubFeaturesMap: new Map([['subFeature1', { baz: 'baz' }]]),
|
||||
};
|
||||
});
|
||||
|
||||
describe('AppFeatures', () => {
|
||||
it('should register enabled kibana features', () => {
|
||||
const featuresSetup = {
|
||||
|
@ -118,4 +151,25 @@ describe('AppFeatures', () => {
|
|||
subFeatures: [{ baz: 'baz' }],
|
||||
});
|
||||
});
|
||||
|
||||
it('should register enabled assistant features', () => {
|
||||
const featuresSetup = {
|
||||
registerKibanaFeature: jest.fn(),
|
||||
} as unknown as PluginSetupContract;
|
||||
|
||||
const appFeatureKeys = ['test-assistant-feature'] as unknown as AppFeatureKeys;
|
||||
|
||||
const appFeatures = new AppFeatures(
|
||||
loggingSystemMock.create().get('mock'),
|
||||
[] as unknown as ExperimentalFeatures
|
||||
);
|
||||
appFeatures.init(featuresSetup);
|
||||
appFeatures.set(appFeatureKeys);
|
||||
|
||||
expect(featuresSetup.registerKibanaFeature).toHaveBeenCalledWith({
|
||||
...ASSISTANT_BASE_CONFIG,
|
||||
...ASSISTANT_APP_FEATURE_CONFIG['test-assistant-feature'],
|
||||
subFeatures: [{ baz: 'baz' }],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -22,9 +22,16 @@ import {
|
|||
import { AppFeaturesConfigMerger } from './app_features_config_merger';
|
||||
import { casesSubFeaturesMap } from './security_cases_kibana_sub_features';
|
||||
import { securitySubFeaturesMap } from './security_kibana_sub_features';
|
||||
import { assistantSubFeaturesMap } from './security_assistant_kibana_sub_features';
|
||||
import {
|
||||
getAssistantAppFeaturesConfig,
|
||||
getAssistantBaseKibanaFeature,
|
||||
getAssistantBaseKibanaSubFeatureIds,
|
||||
} from './security_assistant_kibana_features';
|
||||
|
||||
export class AppFeatures {
|
||||
private securityFeatureConfigMerger: AppFeaturesConfigMerger;
|
||||
private assistantFeatureConfigMerger: AppFeaturesConfigMerger;
|
||||
private casesFeatureConfigMerger: AppFeaturesConfigMerger;
|
||||
private appFeatures?: Set<AppFeatureKey>;
|
||||
private featuresSetup?: FeaturesPluginSetup;
|
||||
|
@ -38,6 +45,10 @@ export class AppFeatures {
|
|||
securitySubFeaturesMap
|
||||
);
|
||||
this.casesFeatureConfigMerger = new AppFeaturesConfigMerger(this.logger, casesSubFeaturesMap);
|
||||
this.assistantFeatureConfigMerger = new AppFeaturesConfigMerger(
|
||||
this.logger,
|
||||
assistantSubFeaturesMap
|
||||
);
|
||||
}
|
||||
|
||||
public init(featuresSetup: FeaturesPluginSetup) {
|
||||
|
@ -98,6 +109,23 @@ export class AppFeatures {
|
|||
this.logger.info(JSON.stringify(completeCasesAppFeatureConfig));
|
||||
|
||||
this.featuresSetup.registerKibanaFeature(completeCasesAppFeatureConfig);
|
||||
|
||||
// register security assistant Kibana features
|
||||
const securityAssistantBaseKibanaFeature = getAssistantBaseKibanaFeature();
|
||||
const securityAssistantBaseKibanaSubFeatureIds = getAssistantBaseKibanaSubFeatureIds();
|
||||
const enabledAssistantAppFeaturesConfigs = this.getEnabledAppFeaturesConfigs(
|
||||
getAssistantAppFeaturesConfig()
|
||||
);
|
||||
const completeAssistantAppFeatureConfig =
|
||||
this.assistantFeatureConfigMerger.mergeAppFeatureConfigs(
|
||||
securityAssistantBaseKibanaFeature,
|
||||
securityAssistantBaseKibanaSubFeatureIds,
|
||||
enabledAssistantAppFeaturesConfigs
|
||||
);
|
||||
|
||||
this.logger.info(JSON.stringify(completeAssistantAppFeatureConfig));
|
||||
|
||||
this.featuresSetup.registerKibanaFeature(completeAssistantAppFeatureConfig);
|
||||
}
|
||||
|
||||
private getEnabledAppFeaturesConfigs(
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
|
||||
import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server';
|
||||
import type { AppFeaturesAssistantConfig, BaseKibanaFeatureConfig } from './types';
|
||||
import { APP_ID, ASSISTANT_FEATURE_ID } from '../../../common/constants';
|
||||
import { AppFeatureAssistantKey } from '../../../common/types/app_features';
|
||||
import type { AssistantSubFeatureId } from './security_assistant_kibana_sub_features';
|
||||
|
||||
export const getAssistantBaseKibanaFeature = (): BaseKibanaFeatureConfig => ({
|
||||
id: ASSISTANT_FEATURE_ID,
|
||||
name: i18n.translate(
|
||||
'xpack.securitySolution.featureRegistry.linkSecuritySolutionAssistantTitle',
|
||||
{
|
||||
defaultMessage: 'Elastic AI Assistant',
|
||||
}
|
||||
),
|
||||
order: 1100,
|
||||
category: DEFAULT_APP_CATEGORIES.security,
|
||||
app: [ASSISTANT_FEATURE_ID, 'kibana'],
|
||||
catalogue: [APP_ID],
|
||||
minimumLicense: 'enterprise',
|
||||
privileges: {
|
||||
all: {
|
||||
api: [],
|
||||
app: [ASSISTANT_FEATURE_ID, 'kibana'],
|
||||
catalogue: [APP_ID],
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
},
|
||||
read: {
|
||||
// No read-only mode currently supported
|
||||
disabled: true,
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const getAssistantBaseKibanaSubFeatureIds = (): AssistantSubFeatureId[] => [
|
||||
// This is a sample sub-feature that can be used for future implementations
|
||||
// AssistantSubFeatureId.createConversation,
|
||||
];
|
||||
|
||||
/**
|
||||
* Maps the AppFeatures keys to Kibana privileges that will be merged
|
||||
* into the base privileges config for the Security app.
|
||||
*
|
||||
* Privileges can be added in different ways:
|
||||
* - `privileges`: the privileges that will be added directly into the main Security Assistant feature.
|
||||
* - `subFeatureIds`: the ids of the sub-features that will be added into the Assistant subFeatures entry.
|
||||
* - `subFeaturesPrivileges`: the privileges that will be added into the existing Assistant subFeature with the privilege `id` specified.
|
||||
*/
|
||||
export const getAssistantAppFeaturesConfig = (): AppFeaturesAssistantConfig => ({
|
||||
[AppFeatureAssistantKey.assistant]: {
|
||||
privileges: {
|
||||
all: {
|
||||
ui: ['ai-assistant'],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
import type { SubFeatureConfig } from '@kbn/features-plugin/common';
|
||||
|
||||
// This is a sample sub-feature that can be used for future implementations
|
||||
// @ts-expect-error unused variable
|
||||
const createConversationSubFeature: SubFeatureConfig = {
|
||||
name: i18n.translate(
|
||||
'xpack.securitySolution.featureRegistry.assistant.createConversationSubFeatureName',
|
||||
{
|
||||
defaultMessage: 'Create Conversations',
|
||||
}
|
||||
),
|
||||
description: i18n.translate(
|
||||
'xpack.securitySolution.featureRegistry.subFeatures.assistant.description',
|
||||
{ defaultMessage: 'Create custom conversations.' }
|
||||
),
|
||||
privilegeGroups: [
|
||||
{
|
||||
groupType: 'independent',
|
||||
privileges: [
|
||||
{
|
||||
api: [],
|
||||
id: 'create_conversation',
|
||||
name: i18n.translate(
|
||||
'xpack.securitySolution.featureRegistry.assistant.createConversationSubFeatureDetails',
|
||||
{
|
||||
defaultMessage: 'Create conversations',
|
||||
}
|
||||
),
|
||||
includeIn: 'all',
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: ['createConversation'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export enum AssistantSubFeatureId {
|
||||
createConversation = 'createConversationSubFeature',
|
||||
}
|
||||
|
||||
// Defines all the ordered Security Assistant subFeatures available
|
||||
export const assistantSubFeaturesMap = Object.freeze(
|
||||
new Map<AssistantSubFeatureId, SubFeatureConfig>([
|
||||
// This is a sample sub-feature that can be used for future implementations
|
||||
// [AssistantSubFeatureId.createConversation, createConversationSubFeature],
|
||||
])
|
||||
);
|
|
@ -7,7 +7,11 @@
|
|||
|
||||
import type { KibanaFeatureConfig, SubFeaturePrivilegeConfig } from '@kbn/features-plugin/common';
|
||||
import type { AppFeatureKey } from '../../../common';
|
||||
import type { AppFeatureSecurityKey, AppFeatureCasesKey } from '../../../common/types/app_features';
|
||||
import type {
|
||||
AppFeatureSecurityKey,
|
||||
AppFeatureCasesKey,
|
||||
AppFeatureAssistantKey,
|
||||
} from '../../../common/types/app_features';
|
||||
import type { RecursivePartial } from '../../../common/utility_types';
|
||||
|
||||
export type BaseKibanaFeatureConfig = Omit<KibanaFeatureConfig, 'subFeatures'>;
|
||||
|
@ -29,3 +33,7 @@ export type AppFeaturesCasesConfig<T extends string = string> = Record<
|
|||
AppFeatureCasesKey,
|
||||
AppFeatureKibanaConfig<T>
|
||||
>;
|
||||
export type AppFeaturesAssistantConfig<T extends string = string> = Record<
|
||||
AppFeatureAssistantKey,
|
||||
AppFeatureKibanaConfig<T>
|
||||
>;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
"feature": {
|
||||
"ml": ["all"],
|
||||
"siem": ["all", "read_alerts", "crud_alerts"],
|
||||
"securitySolutionAssistant": ["all"],
|
||||
"securitySolutionCases": ["all"],
|
||||
"actions": ["read"],
|
||||
"builtInAlerts": ["all"],
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
"feature": {
|
||||
"ml": ["read"],
|
||||
"siem": ["all", "read_alerts", "crud_alerts"],
|
||||
"securitySolutionAssistant": ["all"],
|
||||
"securitySolutionCases": ["all"],
|
||||
"actions": ["read"],
|
||||
"builtInAlerts": ["all"]
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
"feature": {
|
||||
"ml": ["read"],
|
||||
"siem": ["all", "read_alerts", "crud_alerts"],
|
||||
"securitySolutionAssistant": ["all"],
|
||||
"securitySolutionCases": ["all"],
|
||||
"builtInAlerts": ["all"]
|
||||
},
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
"feature": {
|
||||
"ml": ["all"],
|
||||
"siem": ["all", "read_alerts", "crud_alerts"],
|
||||
"securitySolutionAssistant": ["all"],
|
||||
"securitySolutionCases": ["all"],
|
||||
"actions": ["all"],
|
||||
"builtInAlerts": ["all"]
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
"feature": {
|
||||
"ml": ["read"],
|
||||
"siem": ["read", "read_alerts"],
|
||||
"securitySolutionAssistant": ["none"],
|
||||
"securitySolutionCases": ["read"],
|
||||
"actions": ["read"],
|
||||
"builtInAlerts": ["read"]
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
"feature": {
|
||||
"ml": ["read"],
|
||||
"siem": ["all", "read_alerts", "crud_alerts"],
|
||||
"securitySolutionAssistant": ["all"],
|
||||
"securitySolutionCases": ["all"],
|
||||
"actions": ["read"],
|
||||
"builtInAlerts": ["all"]
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
"feature": {
|
||||
"ml": ["read"],
|
||||
"siem": ["all", "read_alerts", "crud_alerts"],
|
||||
"securitySolutionAssistant": ["all"],
|
||||
"securitySolutionCases": ["all"],
|
||||
"actions": ["all"],
|
||||
"builtInAlerts": ["all"]
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"feature": {
|
||||
"ml": ["read"],
|
||||
"siem": ["read", "read_alerts"],
|
||||
"securitySolutionAssistant": ["all"],
|
||||
"securitySolutionCases": ["read"],
|
||||
"actions": ["read"],
|
||||
"builtInAlerts": ["read"]
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
"feature": {
|
||||
"ml": ["read"],
|
||||
"siem": ["read", "read_alerts"],
|
||||
"securitySolutionAssistant": ["all"],
|
||||
"securitySolutionCases": ["read"],
|
||||
"actions": ["read"],
|
||||
"builtInAlerts": ["read"]
|
||||
|
|
|
@ -17,6 +17,7 @@ export const PLI_APP_FEATURES: PliAppFeatures = {
|
|||
essentials: [AppFeatureKey.endpointHostManagement, AppFeatureKey.endpointPolicyManagement],
|
||||
complete: [
|
||||
AppFeatureKey.advancedInsights,
|
||||
AppFeatureKey.assistant,
|
||||
AppFeatureKey.investigationGuide,
|
||||
AppFeatureKey.threatIntelligence,
|
||||
AppFeatureKey.casesConnectors,
|
||||
|
|
|
@ -125,6 +125,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
'uptime',
|
||||
'siem',
|
||||
'slo',
|
||||
'securitySolutionAssistant',
|
||||
'securitySolutionCases',
|
||||
'fleet',
|
||||
'fleetv2',
|
||||
|
|
|
@ -56,6 +56,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
'execute_operations_all',
|
||||
],
|
||||
uptime: ['all', 'read', 'minimal_all', 'minimal_read'],
|
||||
securitySolutionAssistant: ['all', 'read', 'minimal_all', 'minimal_read'],
|
||||
securitySolutionCases: ['all', 'read', 'minimal_all', 'minimal_read', 'cases_delete'],
|
||||
infrastructure: ['all', 'read', 'minimal_all', 'minimal_read'],
|
||||
logs: ['all', 'read', 'minimal_all', 'minimal_read'],
|
||||
|
|
|
@ -42,6 +42,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
osquery: ['all', 'read', 'minimal_all', 'minimal_read'],
|
||||
ml: ['all', 'read', 'minimal_all', 'minimal_read'],
|
||||
siem: ['all', 'read', 'minimal_all', 'minimal_read'],
|
||||
securitySolutionAssistant: ['all', 'read', 'minimal_all', 'minimal_read'],
|
||||
securitySolutionCases: ['all', 'read', 'minimal_all', 'minimal_read'],
|
||||
fleetv2: ['all', 'read', 'minimal_all', 'minimal_read'],
|
||||
fleet: ['all', 'read', 'minimal_all', 'minimal_read'],
|
||||
|
@ -130,6 +131,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
'execute_operations_all',
|
||||
],
|
||||
uptime: ['all', 'read', 'minimal_all', 'minimal_read'],
|
||||
securitySolutionAssistant: ['all', 'read', 'minimal_all', 'minimal_read'],
|
||||
securitySolutionCases: ['all', 'read', 'minimal_all', 'minimal_read', 'cases_delete'],
|
||||
infrastructure: ['all', 'read', 'minimal_all', 'minimal_read'],
|
||||
logs: ['all', 'read', 'minimal_all', 'minimal_read'],
|
||||
|
|
|
@ -77,7 +77,8 @@ export default function navLinksTests({ getService }: FtrProviderContext) {
|
|||
'enterpriseSearchVectorSearch',
|
||||
'appSearch',
|
||||
'workplaceSearch',
|
||||
'guidedOnboardingFeature'
|
||||
'guidedOnboardingFeature',
|
||||
'securitySolutionAssistant'
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue