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

[Security Solution] Fix the feature app list #191965

Merged
merged 11 commits into from
Oct 1, 2024
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;
}
Comment on lines +345 to +353
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the only code addition in this PR, the rest is a small housekeeping refactor.


// 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