Skip to content

Commit

Permalink
[8.x] [Security Solution] Fix the feature app list (elastic#191965) (e…
Browse files Browse the repository at this point in the history
…lastic#194541)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Security Solution] Fix the feature app list
(elastic#191965)](elastic#191965)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Sergi
Massaneda","email":"sergi.massaneda@elastic.co"},"sourceCommit":{"committedDate":"2024-10-01T10:18:17Z","message":"[Security
Solution] Fix the feature app list (elastic#191965)\n\n## Summary\r\n\r\nFixes
https://github.com/elastic/kibana-team/issues/1136\r\n\r\nThe Kibana
feature definition for Security Solution was missing the\r\ncorrect
plugin ID registered in the `app` definition. We were still\r\ndefining
the old _\"securitySolution\"_ app ID in the `app` property,\r\ninstead
of the new _\"securitySolutionUI\"_ ID.\r\n\r\nThe Security Solution
plugin ID change (_\"securitySolution\"_ ->\r\n_\"securitySolutionUI\"_)
was done a long time ago, the inconsistency with\r\nthe Security feature
definition is causing the _Security_ app to still\r\nbe visible in the
global search when the Security feature is disabled:\r\n\r\n- In the
role features\r\n<img width=\"737\" alt=\"Security and Cases
disabled\"\r\nsrc=\"https://github.com/user-attachments/assets/146b8205-90f7-4218-9f1a-7b55c3bad563\">\r\n\r\n-
Or in the space features config\r\n<img width=\"1213\" alt=\"Captura de
pantalla 2024-09-03 a les 15 31
09\"\r\nsrc=\"https://github.com/user-attachments/assets/2563675a-d956-4422-a887-d6d95bcad773\">\r\n\r\n\r\nThis
is fixed now:\r\n\r\nBefore:\r\n<img width=\"1302\" alt=\"Security app
incorrectly
enabled\"\r\nsrc=\"https://github.com/user-attachments/assets/8031f054-7cfb-4098-93c2-eac402501887\">\r\n\r\nAfter:\r\n<img
width=\"1302\" alt=\"Security app disabled
properly\"\r\nsrc=\"https://github.com/user-attachments/assets/a4f38ec2-fb78-4b1b-8c2d-bac58b97ff99\">\r\n\r\n\r\n###
Caveat\r\n\r\nAs per this PR changes:
https://github.com/elastic/kibana/pull/113573\r\nIn the Kibana features
of the role, under the Security catalog, both\r\nSecurity and Cases
features need to be `none` for the Security Solution\r\nplugin to be
disabled. Otherwise, we must enable the plugin and make the\r\nenabled
features available. So, with a role with the following
Kibana\r\nfeatures:\r\n\r\n<img width=\"737\" alt=\"Security disabled
cases
enabled\"\r\nsrc=\"https://github.com/user-attachments/assets/aca8288e-9dd9-49d0-b864-e60273d30759\">\r\n\r\nThe
Security app needs to be available and display only Cases
available:\r\n\r\n<img width=\"247\" alt=\"navigation with only
cases\"\r\nsrc=\"https://github.com/user-attachments/assets/d4866edb-1d1d-4290-a399-76a37536b05c\">\r\n\r\n---------\r\n\r\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"e373e443770399d4b0401b02abc39f794a3ec321","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["bug","release_note:skip","v9.0.0","Team:
SecuritySolution","backport:prev-minor","v8.16.0"],"title":"[Security
Solution] Fix the feature app
list","number":191965,"url":"https://github.com/elastic/kibana/pull/191965","mergeCommit":{"message":"[Security
Solution] Fix the feature app list (elastic#191965)\n\n## Summary\r\n\r\nFixes
https://github.com/elastic/kibana-team/issues/1136\r\n\r\nThe Kibana
feature definition for Security Solution was missing the\r\ncorrect
plugin ID registered in the `app` definition. We were still\r\ndefining
the old _\"securitySolution\"_ app ID in the `app` property,\r\ninstead
of the new _\"securitySolutionUI\"_ ID.\r\n\r\nThe Security Solution
plugin ID change (_\"securitySolution\"_ ->\r\n_\"securitySolutionUI\"_)
was done a long time ago, the inconsistency with\r\nthe Security feature
definition is causing the _Security_ app to still\r\nbe visible in the
global search when the Security feature is disabled:\r\n\r\n- In the
role features\r\n<img width=\"737\" alt=\"Security and Cases
disabled\"\r\nsrc=\"https://github.com/user-attachments/assets/146b8205-90f7-4218-9f1a-7b55c3bad563\">\r\n\r\n-
Or in the space features config\r\n<img width=\"1213\" alt=\"Captura de
pantalla 2024-09-03 a les 15 31
09\"\r\nsrc=\"https://github.com/user-attachments/assets/2563675a-d956-4422-a887-d6d95bcad773\">\r\n\r\n\r\nThis
is fixed now:\r\n\r\nBefore:\r\n<img width=\"1302\" alt=\"Security app
incorrectly
enabled\"\r\nsrc=\"https://github.com/user-attachments/assets/8031f054-7cfb-4098-93c2-eac402501887\">\r\n\r\nAfter:\r\n<img
width=\"1302\" alt=\"Security app disabled
properly\"\r\nsrc=\"https://github.com/user-attachments/assets/a4f38ec2-fb78-4b1b-8c2d-bac58b97ff99\">\r\n\r\n\r\n###
Caveat\r\n\r\nAs per this PR changes:
https://github.com/elastic/kibana/pull/113573\r\nIn the Kibana features
of the role, under the Security catalog, both\r\nSecurity and Cases
features need to be `none` for the Security Solution\r\nplugin to be
disabled. Otherwise, we must enable the plugin and make the\r\nenabled
features available. So, with a role with the following
Kibana\r\nfeatures:\r\n\r\n<img width=\"737\" alt=\"Security disabled
cases
enabled\"\r\nsrc=\"https://github.com/user-attachments/assets/aca8288e-9dd9-49d0-b864-e60273d30759\">\r\n\r\nThe
Security app needs to be available and display only Cases
available:\r\n\r\n<img width=\"247\" alt=\"navigation with only
cases\"\r\nsrc=\"https://github.com/user-attachments/assets/d4866edb-1d1d-4290-a399-76a37536b05c\">\r\n\r\n---------\r\n\r\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"e373e443770399d4b0401b02abc39f794a3ec321"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/191965","number":191965,"mergeCommit":{"message":"[Security
Solution] Fix the feature app list (elastic#191965)\n\n## Summary\r\n\r\nFixes
https://github.com/elastic/kibana-team/issues/1136\r\n\r\nThe Kibana
feature definition for Security Solution was missing the\r\ncorrect
plugin ID registered in the `app` definition. We were still\r\ndefining
the old _\"securitySolution\"_ app ID in the `app` property,\r\ninstead
of the new _\"securitySolutionUI\"_ ID.\r\n\r\nThe Security Solution
plugin ID change (_\"securitySolution\"_ ->\r\n_\"securitySolutionUI\"_)
was done a long time ago, the inconsistency with\r\nthe Security feature
definition is causing the _Security_ app to still\r\nbe visible in the
global search when the Security feature is disabled:\r\n\r\n- In the
role features\r\n<img width=\"737\" alt=\"Security and Cases
disabled\"\r\nsrc=\"https://github.com/user-attachments/assets/146b8205-90f7-4218-9f1a-7b55c3bad563\">\r\n\r\n-
Or in the space features config\r\n<img width=\"1213\" alt=\"Captura de
pantalla 2024-09-03 a les 15 31
09\"\r\nsrc=\"https://github.com/user-attachments/assets/2563675a-d956-4422-a887-d6d95bcad773\">\r\n\r\n\r\nThis
is fixed now:\r\n\r\nBefore:\r\n<img width=\"1302\" alt=\"Security app
incorrectly
enabled\"\r\nsrc=\"https://github.com/user-attachments/assets/8031f054-7cfb-4098-93c2-eac402501887\">\r\n\r\nAfter:\r\n<img
width=\"1302\" alt=\"Security app disabled
properly\"\r\nsrc=\"https://github.com/user-attachments/assets/a4f38ec2-fb78-4b1b-8c2d-bac58b97ff99\">\r\n\r\n\r\n###
Caveat\r\n\r\nAs per this PR changes:
https://github.com/elastic/kibana/pull/113573\r\nIn the Kibana features
of the role, under the Security catalog, both\r\nSecurity and Cases
features need to be `none` for the Security Solution\r\nplugin to be
disabled. Otherwise, we must enable the plugin and make the\r\nenabled
features available. So, with a role with the following
Kibana\r\nfeatures:\r\n\r\n<img width=\"737\" alt=\"Security disabled
cases
enabled\"\r\nsrc=\"https://github.com/user-attachments/assets/aca8288e-9dd9-49d0-b864-e60273d30759\">\r\n\r\nThe
Security app needs to be available and display only Cases
available:\r\n\r\n<img width=\"247\" alt=\"navigation with only
cases\"\r\nsrc=\"https://github.com/user-attachments/assets/d4866edb-1d1d-4290-a399-76a37536b05c\">\r\n\r\n---------\r\n\r\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"e373e443770399d4b0401b02abc39f794a3ec321"}},{"branch":"8.x","label":"v8.16.0","branchLabelMappingKey":"^v8.16.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Sergi Massaneda <sergi.massaneda@elastic.co>
  • Loading branch information
kibanamachine and semd authored Oct 1, 2024
1 parent 631cba3 commit 344512f
Showing 1 changed file with 106 additions and 89 deletions.
195 changes: 106 additions & 89 deletions x-pack/plugins/security_solution/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type {
PluginInitializerContext,
Plugin as IPlugin,
} from '@kbn/core/public';
import { DEFAULT_APP_CATEGORIES } from '@kbn/core/public';
import { AppStatus, DEFAULT_APP_CATEGORIES } from '@kbn/core/public';
import { Storage } from '@kbn/kibana-utils-plugin/public';
import type { TriggersAndActionsUIPublicPluginSetup } from '@kbn/triggers-actions-ui-plugin/public';
import { uiMetricService } from '@kbn/cloud-security-posture-common/utils/ui_metrics';
Expand Down Expand Up @@ -208,88 +208,20 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S

public start(core: CoreStart, plugins: StartPlugins): PluginStart {
this.services.start(core, plugins);

if (plugins.fleet) {
const { registerExtension } = plugins.fleet;
const registerOptions: FleetUiExtensionGetterOptions = {
coreStart: core,
depsStart: plugins,
services: {
upsellingService: this.contract.upsellingService,
},
};

registerExtension({
package: 'endpoint',
view: 'package-policy-edit',
Component: getLazyEndpointPolicyEditExtension(registerOptions),
});

registerExtension({
package: 'endpoint',
view: 'package-policy-response',
Component: getLazyEndpointPolicyResponseExtension(registerOptions),
});

registerExtension({
package: 'endpoint',
view: 'package-generic-errors-list',
Component: getLazyEndpointGenericErrorsListExtension(registerOptions),
});

registerExtension({
package: 'endpoint',
view: 'package-policy-create',
Component: getLazyEndpointPolicyCreateExtension(registerOptions),
});

registerExtension({
package: 'endpoint',
view: 'package-policy-create-multi-step',
Component: LazyEndpointPolicyCreateMultiStepExtension,
});

registerExtension({
package: 'endpoint',
view: 'package-detail-custom',
Component: getLazyEndpointPackageCustomExtension(registerOptions),
});

registerExtension({
package: 'endpoint',
view: 'package-detail-assets',
Component: LazyEndpointCustomAssetsExtension,
});

registerExtension({
package: 'endpoint',
view: 'endpoint-agent-tamper-protection',
Component: getLazyEndpointAgentTamperProtectionExtension(registerOptions),
});

registerExtension({
package: 'cloud_security_posture',
view: 'pli-auth-block',
Component: getLazyCloudSecurityPosturePliAuthBlockExtension(registerOptions),
});

registerExtension({
package: 'cribl',
view: 'package-policy-replace-define-step',
Component: LazyCustomCriblExtension,
});
}

// Not using await to prevent blocking start execution
this.registerAppLinks(core, plugins);

this.registerFleetExtensions(core, plugins);
this.registerPluginUpdates(core, plugins); // Not awaiting to prevent blocking start execution
return this.contract.getStartContract(core);
}

public stop() {
this.services.stop();
}

/**
* SubPlugins are the individual building blocks of the Security Solution plugin.
* They are lazily instantiated to improve startup time.
* TODO: Move these functions to ./lazy_sub_plugins.ts
*/
private async createSubPlugins(): Promise<SubPlugins> {
if (!this._subPlugins) {
const { subPluginClasses } = await this.lazySubPlugins();
Expand Down Expand Up @@ -317,9 +249,6 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
return this._subPlugins;
}

/**
* All started subPlugins.
*/
private async startSubPlugins(
storage: Storage,
core: CoreStart,
Expand Down Expand Up @@ -389,7 +318,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
}

/**
* Registers the alerts tables configurations.
* Registers the alerts tables configurations to the triggersActionsUi plugin.
*/
private async registerAlertsTableConfiguration(
triggersActionsUi: TriggersAndActionsUIPublicPluginSetup
Expand All @@ -406,38 +335,126 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
}

/**
* Registers deepLinks and appUpdater for appLinks using license.
* Registers the plugin updates including status, visibleIn, and deepLinks via the plugin updater$.
*/
async registerAppLinks(core: CoreStart, plugins: StartPlugins) {
private async registerPluginUpdates(core: CoreStart, plugins: StartPlugins) {
const { license$ } = plugins.licensing;
const { capabilities } = core.application;
const { upsellingService, isSolutionNavigationEnabled$ } = this.contract;

// When the user does not have access to SIEM (main Security feature) nor Security Cases feature, the plugin must be inaccessible.
if (!capabilities.siem?.show && !capabilities.securitySolutionCases?.read_cases) {
this.appUpdater$.next(() => ({
status: AppStatus.inaccessible,
visibleIn: [],
}));
// no need to register the links updater when the plugin is inaccessible
return;
}

// Configuration of AppLinks updater registration based on license and capabilities
const {
appLinks: initialAppLinks,
getFilteredLinks,
solutionAppLinksSwitcher,
} = await this.lazyApplicationLinks();
const { license$ } = plugins.licensing;
const { upsellingService, isSolutionNavigationEnabled$ } = this.contract;

registerDeepLinksUpdater(this.appUpdater$, isSolutionNavigationEnabled$);

const appLinks$ = new Subject<AppLinkItems>();
appLinks$.next(initialAppLinks);
const appLinksToUpdate$ = new Subject<AppLinkItems>();
appLinksToUpdate$.next(initialAppLinks);

appLinks$
appLinksToUpdate$
.pipe(combineLatestWith(license$, isSolutionNavigationEnabled$))
.subscribe(([appLinks, license, isSolutionNavigationEnabled]) => {
const links = isSolutionNavigationEnabled ? solutionAppLinksSwitcher(appLinks) : appLinks;
const linksPermissions: LinksPermissions = {
experimentalFeatures: this.experimentalFeatures,
upselling: upsellingService,
capabilities: core.application.capabilities,
capabilities,
uiSettingsClient: core.uiSettings,
...(license.type != null && { license }),
};
updateAppLinks(links, linksPermissions);
});

const filteredLinks = await getFilteredLinks(core, plugins);
appLinks$.next(filteredLinks);
appLinksToUpdate$.next(filteredLinks);
}

private registerFleetExtensions(core: CoreStart, plugins: StartPlugins) {
if (!plugins.fleet) {
return;
}

const { registerExtension } = plugins.fleet;
const registerOptions: FleetUiExtensionGetterOptions = {
coreStart: core,
depsStart: plugins,
services: {
upsellingService: this.contract.upsellingService,
},
};

registerExtension({
package: 'endpoint',
view: 'package-policy-edit',
Component: getLazyEndpointPolicyEditExtension(registerOptions),
});

registerExtension({
package: 'endpoint',
view: 'package-policy-response',
Component: getLazyEndpointPolicyResponseExtension(registerOptions),
});

registerExtension({
package: 'endpoint',
view: 'package-generic-errors-list',
Component: getLazyEndpointGenericErrorsListExtension(registerOptions),
});

registerExtension({
package: 'endpoint',
view: 'package-policy-create',
Component: getLazyEndpointPolicyCreateExtension(registerOptions),
});

registerExtension({
package: 'endpoint',
view: 'package-policy-create-multi-step',
Component: LazyEndpointPolicyCreateMultiStepExtension,
});

registerExtension({
package: 'endpoint',
view: 'package-detail-custom',
Component: getLazyEndpointPackageCustomExtension(registerOptions),
});

registerExtension({
package: 'endpoint',
view: 'package-detail-assets',
Component: LazyEndpointCustomAssetsExtension,
});

registerExtension({
package: 'endpoint',
view: 'endpoint-agent-tamper-protection',
Component: getLazyEndpointAgentTamperProtectionExtension(registerOptions),
});

registerExtension({
package: 'cloud_security_posture',
view: 'pli-auth-block',
Component: getLazyCloudSecurityPosturePliAuthBlockExtension(registerOptions),
});

registerExtension({
package: 'cribl',
view: 'package-policy-replace-define-step',
Component: LazyCustomCriblExtension,
});
}

// Lazy loaded dependencies
Expand Down

0 comments on commit 344512f

Please sign in to comment.