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

[8.x] [Security Solution] Fix the feature app list (#191965) #194541

Merged
merged 1 commit into from
Oct 1, 2024
Merged
Changes from all commits
Commits
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
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